Calcolo volume in C

di il
5 risposte

Calcolo volume in C

Testo:
Cattura.PNG
Cattura.PNG


Cattura1.PNG
Cattura1.PNG

Il mio codice ha il problema che dopo la prima interazione del ciclo in cui aumenta d esce dal programma perchè l'errore è maggiore di epsilon, qualcuno può aiutarmi a capire perchè?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define NMAX 1000000
#define NITER 15
#define EPSILON 0.01
#define G 9.80665
void inserimento(char *msg, char *fmt, void *v);
double Calotta(double R, double d);
void PrintResults(double v[][3], int size);
int main() {
    srand(time(NULL));
    double R, p, m, Vmc, incremento, d, Forza[NITER][3];
    d = 0.0;
    int fine = 0, n;
    while (!fine) {
      inserimento("Inserire il valore del raggio della sfera: ", "%lf", &R);
      inserimento("Inserire il valore della massa della sfera: ", "%lf", &m);
      inserimento("Inserire il valore della densita' della sfera: ", "%lf", &p);
      if (R <= 0 || m <= 0 || p <=0) {
          printf("ERRORE: le grandezze inserite devono essere positive!\n");
          fine=0;
      }
      else  
        fine=1;
    }
    for (n = 0; n < NITER; n++) {
        incremento = (0.8*R)*rand()/((double)RAND_MAX);
        Vmc = Calotta(R,d);
        Forza[n][0] = d;
        Forza[n][1] = fabs(G*p*Vmc);
        Forza[n][2] = m*G;
        d += incremento;
    }
    PrintResults(Forza,NITER); 
}

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 Calotta(double R, double d) {
    double Vparal, x, y, z, h, Vcalotta, Vmc;
    unsigned long long int np = 0;
    int i;
    Vparal = (2*R * 2*R)*(R - d);
    for (i = 0; i < NMAX; i++) {
        x = (2*R) * rand()/((double)RAND_MAX) - R;
        y = (2*R) * rand()/((double)RAND_MAX) - R;
        z = (R - d) * rand()/((double)RAND_MAX) + d;
        if ((x*x + y*y + z*z <= R*R)) 
            np++;
    }
    Vmc = Vparal * np/NMAX;
    h = R - d;
    Vcalotta = M_PI*h*h*(R - h/3.0);
    if (fabs(Vmc - Vcalotta)/(Vcalotta) > EPSILON) {
        printf("Errore maggiore di epsilon\n");
        exit(0);
    }
    else 
        return Vmc;
}

void PrintResults(double v[][3], int size) {
    FILE *f;
    int i;
    f = fopen("Archimede.dat","w");
    for (i = 0; i < size; i++) {
        fprintf(f,"%10.4lf %10.4lf %10.4lf\n",v[i][0], v[i][1], v[i][2]);
    }
    fclose(f);
}

5 Risposte

  • Re: Calcolo volume in C

    Premesso che il codice potrebbe essere ottimizzato e reso molto più chiaro, farei alcune osservazioni:
    - non hai definito M_PI;
    - il formato dei double nella printf() è %f e non %lf, quindi credo che lo stesso valga anche per la funzione fprintf();
    - a cosa serve il valore assoluto in questo caso?
    Forza[n][1] = fabs(G*p*Vmc);
    - in ogni caso l'errore vero e proprio sta nella modifica della variabile d nel main(). In pratica tu partendo da 0 incrementi la variabile d di una quantità casuale compresa nell'intervallo [0;R*0.8]; ti renderai conto che in questo caso bastano solo due incrementi affinché d possa assumere un valore maggiore di R. Inoltre quando la traccia dice di modificare automaticamente d, credo che non si riferisca a qualcosa di casuale, ma semplicemente a suddividere equamente l'intervallo [0;R*0.8] in NITER parti.
    Qualcosa del genere insomma:
    for(unsigned int n = 0; n < NITER; ++n) 
    {
        d = n * 0.8 * R / (NITER - 1);
        ...
  • Re: Calcolo volume in C

    Gcc definisce M_PI in math.h

    Il Visual C/C++ ha necessità di usare

    #define _USE_MATH_DEFINES
    #include <math.h>
  • Re: Calcolo volume in C

    Gli era già stato fatto notare di scrivere
    
    #ifndef M_PI
        #define M_PI 3.14159265358979323846
    #endif
    
    Ma giustamente se ne sbatte. L'importante è risolvere il suo di problema, fatti degli altri se non compila
  • Re: Calcolo volume in C

    @Nippolo
    -Non ho definito M_PI perchè è definito automaticamente in math.h, ed inoltre non mi è stato mai chiesto dal mio professore di definire fino alla 150milionesima crifra il valore di pi-greco, ne io ritenevo che l'approssimazione di math.h fosse cosi grossolana.
    -Stessa cosa per questa osservazione, sia sul libro che dal mio prof mi è stato sempre detto di utilizzare il formato %lf, comunque, se è come dici tu, dalla prossima volta usero %f
    - ho usato il valore assoluto perchè si richiedeva che G*p*Vmc fosse senza segno, anche se immaginavo fosse inutile

    Per quanto riguarda la modifica che mi hai suggerito ho modificato cosi l'ultimo ciclo:
    for (n = 0; n < NITER; ++n) {
            d = n * 0.8 * R / (NITER - 1);
            Vmc = Calotta(R,d);
            Forza[n][0] = d;
            Forza[n][1] = G*p*Vmc;
            Forza[n][2] = m*G;
        }
    @Weierstrass Stessa cosa che ho risposto prima a Nippolo
  • Re: Calcolo volume in C

    Nexus99 ha scritto:


    @Nippolo
    -Non ho definito M_PI perchè è definito automaticamente in math.h, ed inoltre non mi è stato mai chiesto dal mio professore di definire fino alla 150milionesima crifra il valore di pi-greco, ne io ritenevo che l'approssimazione di math.h fosse cosi grossolana.
    Non c'entra niente l'approssimazione, il punto è che non tutti i compilatori riconoscono quella costante.

    Nexus99 ha scritto:


    -Stessa cosa per questa osservazione, sia sul libro che dal mio prof mi è stato sempre detto di utilizzare il formato %lf, comunque, se è come dici tu, dalla prossima volta usero %f
    Io non ho letto nessun libro e ascoltato nessun prof, ti parlo semplicemente da qualcuno che davanti ad un'evidenza sperimentale (il formato %lf non funzionava per stampare un double) ha fatto una ricerca in rete e approfondito la questione:
    https://stackoverflow.com/questions/4264127/correct-format-specifier-for-double-in-printf

    Nexus99 ha scritto:


    ho usato il valore assoluto perchè si richiedeva che G*p*Vmc fosse senza segno, anche se immaginavo fosse inutile
    Credo che il testo lo specificasse vista la natura vettoriale delle forze. In ogni caso se pensi una cosa non farti fuorviare e agisci di conseguenza!
Devi accedere o registrarti per scrivere nel forum
5 risposte