Mi sono bloccato in un punto di questo programma, mi date un aiutino?

di il
7 risposte

Mi sono bloccato in un punto di questo programma, mi date un aiutino?

Testo;
Si deve scrivere un programma chiamato molla.c per calcolare numericamente l’andamento temporale
di x(t), in particolare il programma dovrà:
1. Chiedere in input la costante elastica della molla k (in N/m), la massa m (in kg), a e xmax,
verificando che k, m e xmax siano grandezze positive.
2. Calcolare il periodo Thar valido per piccole oscillazioni e stamparlo con 5 cifre dopo la virgola.
Thar = 2*p*sqrt(m/k)
3. Calcolare e stampare in notazione scientifica il passo temporale ?t utilizzando la seguente
formula:
?t =Thar/(2^20)
4. Inizializzare t, x e v (ovvero porre t = 0, x = xmax e v = 0).
5. Calcolare x e v al tempo t + ?t effettuando un passo d’integrazione tramite le equazioni (1)
e (2).
(1) = v += -(k/m)*(x + alpha*x*x*x)*dt
(2) = x += v*dt
6. Aggiornare il tempo t incrementandolo di ?t.
7. Calcolare il prodotto P = x(t + ?t)x(t). Si noti che se P < 0 allora si è trovato uno zero di
x(t). Dunque nel caso in cui P < 0, memorizzare il valore attuale di t in un array chiamato Ts.
Risulterà quindi che il primo elemento di Ts è il tempo a cui abbiamo trovato il primo zero di
x(t), il secondo elemento quello a cui abbiamo trovato il secondo zero e così via.
8. Se il numero di zeri di x(t) è pari a 3 il ciclo sui passi d’integrazione deve terminare, altrimenti
si torna al punto 5.
9. Una stima numerica Test del periodo sarà pari alla differenza tra l’ultimo (cioè il
terzo) ed il primo elemento dell’array Ts.
10. Stampare il periodo calcolato numericamente Test con 5 cifre dopo la virgola.
Nello scrivere il programma si richiede che vengano implementate le seguenti funzioni:
• inserimento(...), che richiede l’inserimento di un numero numero in virgola mobile
• passo(...), che effettuerà un singolo passo d’integrazione aggiornando i valori di x e v tramite
le equazioni (1) e (2).
• force(...), che dati x, k, m e a restituisce il valore -(k/m)*(x + ax^3)
Infine si calcoli il valore di Test per k = 9.8 N/m, m = 1 kg, a = -1/6 e xmax = 0.0175 m e si riporti
il risultato nel file periodo-stimato.tx

Mio svolgimento:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
void inserimento(char *msg, char *fmt, void *v);
double force(double x, double k, double m, double alpha);
void passo(double *v, double *x, double m, double k, double alpha, double t);
int main() {
    double xmax, k, m, alpha;
    int fine = 0;
    while (!fine) {
        inserimento("Inserisci il valore della costante elastica ", "%lf", &k);
        inserimento("Inserisci il valore della massa ", "%lf", &m);
        inserimento("Inserisci il valore della ampiezza massima delle oscillazioni ", "%lf", &xmax);
        if (k <= 0 || m <= 0 || xmax <= 0) {
            printf("ERRORE:Le quantita' inserite devono essere positive\n");
            fine=0;
        }
        else
            fine=1;
    }
    inserimento("Inserisci il valore di alpha ", "%lf", &alpha);
    double Thar = 2*M_PI*sqrt(m/k);
    printf("Il periodo valido per piccole oscillazioni e': %.5lf\n",Thar);
    double dt = Thar/pow(2,20);
    printf("Il passo temporale vale: %e\n",dt);
    double v, x, t, Ts[3];
    v = 0;
    x = xmax;
    t = 0;
    int i = 0, zeri = 0;
    do {
        passo(&v,&x,m,k,alpha,t);
        if (xmax*x < 0) {
            Ts[i] = t;
            i++;
            zeri++;
        }
        t += dt;
        xmax = x;
    } while (zeri < 3);
    double Test;
    Test = Ts[2] - Ts[0];
    printf("Una stima numerica del periodo della molla e' pari a; %.5lf\n",Test);
}

void inserimento(char *msg, char *fmt, void *v)
{
  int fine, res, c;
  fine=0;
  while (!fine)
    {
      printf("%s", msg);
      fine=1;
      res=scanf(fmt, v);
      if (ferror(stdin)||feof(stdin))
        {
          printf("\n");
          clearerr(stdin);
          fine=0;
          continue;
        }
          
      if (res < 1)
        {
          printf("Problema nella conversione\n");
          fine=0;
        }
      while ((c=getchar())!='\n'); 
    }
}

double force(double x, double k, double m, double alpha) {
    return (-k/m)*(x + alpha*x*x*x);
}

void passo(double *v, double *x, double m, double k, double alpha, double t) {
    double tempx = *x;
    double tempv = *v;
    tempv += force(tempx,k,m,alpha)*t;
    tempx += force(tempx,k,m,alpha)*t*t;
    *x = tempx;
    *v = tempv;
}
Il programma esegue all'infinito, probabilmente perchè zeri non è mai 3, qualcuno sa dirmi come mai?

7 Risposte

  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    Aggiornamento:
    Se scrivo:
    tempx += tempv*t;
    il programma esegue, ma non calcola correttamente il periodo per k=9.8 , m=1, xmax = 0.0175 e alpha = -1/6, che dovrebbe essere questo in figura:
    Cattura.PNG
    Cattura.PNG

  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    E' colpa del tuo professore che non conosce bene i double

    prova così (occhio ai punti e ai segni e dagli qualche secondo per calcolare)
    
    #include <stdio.h>
    #include <math.h>
    
    #ifndef M_PI
        #define M_PI 3.14159265358979323846
    #endif
    
    int main() {
        double x, k, m, alpha;
        do{
            printf("Inserisci il valore della costante elastica: ");
            scanf(" %lf", &k);
            printf("Inserisci il valore della massa: ");
            scanf(" %lf", &m);     
            printf("Inserisci il valore della ampiezza massima delle oscillazioni: ");
            scanf(" %lf", &x);           
            if (k <= 0.0 || m <= 0.0 || x <= 0.0)
                printf("ERRORE: le quantita' inserite devono essere positive\n");
        }while (k <= 0 || m <= 0 || x <= 0);   
        printf("Inserisci il valore di alpha: ");
        scanf(" %lf", &alpha);    
        double Thar = 2.0*M_PI*sqrt(m/k);
        printf("Il periodo valido per piccole oscillazioni e': %.5lf\n",Thar);
        double dt = Thar*2e-20;
        printf("Il passo temporale vale: %e\n",dt);
        double x_old, v, v_old, t, Ts[3];
        int zeri = 0;
        v = 0.0;
        t = 0.0;
        do {
            v_old = v;
            x_old = x;        
            t += dt;
            v -= k * dt * (x + alpha*x*x*x)/m;
            x += v * dt;      
            while(x_old == x || v == v_old){
                x = x_old;
                v = v_old;
                t -= dt;
                dt += dt;
                printf("Il passo temporale e' stato aumentato e ora vale: %e\n",dt);
                t += dt;
                v -= k * dt * (x + alpha*x*x*x)/m;
                x += v * dt;
            }
            if (x_old*x <= 0)
                Ts[zeri++] = t;
        } while (zeri < 3);
        double Test = Ts[2] - Ts[0];
        printf("Una stima numerica del periodo della molla e' pari a; %.5lf\n", Test);
        getchar();
        return 0;
    }
    
  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    Il tuo funziona però dovrei farlo con le funzioni come da istruzione. Che cosa dovrei cambiare?
    PS. il getchar alla fine del tuo programma a cosa serve?
  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    L'ho fatto con le istruzioni da traccia. Il problema è che il professore non ha tenuto conto della precisione dei double. Chiedi a lui perché

    Getchar() è per aspettare che l'utente prema un tasto. Non serve
  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    Beh ma il testo chiede esplicitamente di usare una funzione passo ed una force.... che è proprio il punto che sembra non funzionare del mio programma.
    Mi chiedevo se magari potessi implementare nel tuo programma queste funzioni, in modo da capire dove sbaglio.
    Per quanto riguarda i double questo era un compito d'esame dell'anno passato quindi non so come abbiano fatto
  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    Le funzioni non sono il problema. Il problema sono le formule
    
                v -= k * dt * (x + alpha*x*x*x)/m;
                x += v * dt;
    
    Se la coppia (x,v) non cambia durante l'iterazione, sei sempre bloccato sullo stesso punto e l'algoritmo non procede. La traccia non tiene conto di questo fatto. Prova tu a pensare a un rimedio, il mio funziona ma non è del tutto corretto.

    Quando procede, l'algoritmo è molto lento: metti delle printf per x e t per vedere a che punto della traiettoria sei.

    Anche il criterio di attraversamento degli zeri non è del tutto corretto (anche da traccia): manca il caso, poco probabile ma possibile, in cui arrivi sullo zero spaccato con x
  • Re: Mi sono bloccato in un punto di questo programma, mi date un aiutino?

    Comunque è bastato mettere dt al posto di t in passo, cosa che secondo me non ha senso però ok.
    Cosi sembra anche abbastanza veloce
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    void inserimento(char *msg, char *fmt, void *v);
    double force(double x, double k, double m, double alpha);
    void passo(double *v, double *x, double m, double k, double alpha, double t);
    int main() {
        double xmax, k, m, alpha;
        int fine = 0;
        while (!fine) {
            inserimento("Inserisci il valore della costante elastica ", "%lf", &k);
            inserimento("Inserisci il valore della massa ", "%lf", &m);
            inserimento("Inserisci il valore della ampiezza massima delle oscillazioni ", "%lf", &xmax);
            if (k <= 0 || m <= 0 || xmax <= 0) {
                printf("ERRORE:Le quantita' inserite devono essere positive\n");
                fine=0;
            }
            else
                fine=1;
        }
        inserimento("Inserisci il valore di alpha ", "%lf", &alpha);
        double Thar = 2*M_PI*sqrt(m/k);
        printf("Il periodo valido per piccole oscillazioni e': %.5lf\n",Thar);
        double dt = Thar/pow(2,20);
        printf("Il passo temporale vale: %e\n",dt);
        double v, x, t, Ts[3];
        v = 0;
        x = xmax;
        t = 0;
        int zeri = 0;
        do {
            passo(&v,&x,m,k,alpha,dt);
            if (xmax*x < 0) {
                Ts[zeri++] = t;
            }
            t += dt;
            xmax = x;
        } while (zeri < 3);
        double Test;
        Test = Ts[2] - Ts[0];
        printf("Una stima numerica del periodo della molla e' pari a; %.5lf\n",Test);
    }
    
    void inserimento(char *msg, char *fmt, void *v)
    {
      int fine, res, c;
      fine=0;
      while (!fine)
        {
          printf("%s", msg);
          fine=1;
          res=scanf(fmt, v);
          if (ferror(stdin)||feof(stdin))
            {
              printf("\n");
              clearerr(stdin);
              fine=0;
              continue;
            }
              
          if (res < 1)
            {
              printf("Problema nella conversione\n");
              fine=0;
            }
          while ((c=getchar())!='\n'); 
        }
    }
    
    double force(double x, double k, double m, double alpha) {
        return (-k/m)*(x + alpha*x*x*x);
    }
    
    void passo(double *v, double *x, double m, double k, double alpha, double t) {
        double tempx = *x;
        double tempv = *v;
        tempv += force(tempx,k,m,alpha)*t;
        tempx += tempv*t;
        *x = tempx;
        *v = tempv;
    }
Devi accedere o registrarti per scrivere nel forum
7 risposte