Mi fate questo calcolo, mi si blocca la compilazione!!

di il
6 risposte

Mi fate questo calcolo, mi si blocca la compilazione!!

Salve,
devo rispondere a questa domanda:
Quanti termini di questa serie dovete utilizzare per ottenere i valori
3,14 ?[ ? ]
3,141 ?[ ? ]
3,1415 ?[p approssimato a 10188 termini = 3.141500]
3,14159 ?[p approssimato a 159784 termini = 3.141590]

// ESERCIZIO 4.26: calcolo del valore di p.
//Calcolate il valore di p in base alla serie infinita ....
//      p = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ....
// Stampate una tabella che mostri il valore di p approsimato da un termine di questa serie, da due termini, da tre e così via. Quanti termini di questa serie dovete utilizzare per ottenere i valori 3,14? 3,141? 3,1415?[p approssimato a 10188 termini: 3.141500] 3,14159?[p approssimato a 159784 termini: 3.141590]

// Codice sorgente:
#include <stdio.h>
int main (void) {
    puts( "Questa è una tabella che mostra il valore di p secondo la serie infinita:\np = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ....\napprossimato ad un termine della serie, a due, a tre e così via.\n");
    float piGreco = 4;
    int termineCounter = 1;
    printf( "p approssimato ad un %d termine:\t\t%f\n", termineCounter, piGreco );
    float dispariCounter = 3; 
    termineCounter = 2;
    while ( termineCounter <= 10000000 ) {
        int resto = termineCounter % 2;
        if ( resto == 1 ) {
            piGreco = piGreco + 4 / dispariCounter;  
            printf( "p approssimato a %d termini:\t\t%f\n", termineCounter, piGreco );            
        } else {
            piGreco = piGreco - 4 / dispariCounter; 
            printf( "p approssimato a %d termini:\t\t%f\n", termineCounter, piGreco );             
        }
        dispariCounter = dispariCounter + 2;
        ++termineCounter;
        float valore = 3.14100;
        if ( piGreco == valore ) {
          break;
        }
    }
    
}
http://prntscr.com/hdj1s

Grazie.

6 Risposte

  • Re: Mi fate questo calcolo, mi si blocca la compilazione!!

    Qual è il problema? Vuoi che rispondiamo alla domanda che ti è stata posta oppure hai qualche problema con il codice?
  • Re: Mi fate questo calcolo, mi si blocca la compilazione!!

    Intanto lavora con i double e non con i float ...
  • Re: Mi fate questo calcolo, mi si blocca la compilazione!!

    Il motivo per cui ti si blocca e' il seguente:
    
    float valore = 3.14100;
            if ( piGreco == valore ) {
              break;
            }
    
    NON PUOI CONFRONTARE DEI FLOATING POINT PER UGUAGLIANZA:

    la probabilita' che tu possa ottenere ESATTAMENTE il valore richiesto e' praticamente nulla.
    Per capitare puo' anche capitare, ma e' meglio non farci affidamento. Anzi, partire dall'idea che NON CAPITA MAI.

    La spiegazione del motivo e' un corso semestrale all'universita'!

    Puoi sempre confronare due floating con "<, <=, >, >=" ma MAI per "==, !="
    Invece di usare x == y oppure x != y DEVI usare abs(x-y) <= eps oppure abs(x-y) > eps

    per un qualche eps/ilon, numero piccolo.

    Ma anche il valore di eps NON PUO" ESSERE TROPPO PICCOLO, altrimenti la disuguaglianza potrebbe non verificarsi mai.
  • Re: Mi fate questo calcolo, mi si blocca la compilazione!!

    candaluar ha scritto:


    Qual è il problema? Vuoi che rispondiamo alla domanda che ti è stata posta oppure hai qualche problema con il codice?
    Il problema è che il codice è semplice ed è fatto correttamente, a parte
    oregon
    lavorare con i double anzi che con i float? Perchè??...scusa la mia ignoranza. Cmq il problema è che forse la mia RAM è scarsa e non riesce ad eseguire tutti i calcoli.
    Insomma...per trovare quanti termini della serie ci vogliono per ottenere 3.1415 la "RAM" ce la fa 3,1415?[p approssimato a 10188 termini: 3.141500] per 3,14159?[p approssimato a 159784 termini: 3.141590] anche... ma per operazioni superiori a 1,800,000 circa non ce la fa si blocca... Prima si bloccava anche ad 1,200,000 ops.
    Questo perchè l'esercizio chiede di trovare p dalla serie infinita: p = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + .... Poi chiede: Stampate una tabella che mostri il valore di p approsimato da un termine di questa serie, da due termini, da tre e così via. Poi chiede: Quanti termini di questa serie dovete utilizzare per ottenere i valori 3,14? 3,141? 3,1415? 3,14159?
    Per trovarli uso un break quando piGreco == 3.14etc... Per 3,1415 OK cioè [p approssimato a 10188 termini: 3.141500] per 3,14159 OK cioè [p approssimato a 159784 termini: 3.141590] ma me ne restano 2. 3.141 e 3.14 Si dovrebbe cambiare il valore di piGreco prima dell' istruzione break nell'If.
    La mia RAM è 4,00 GB. Processore Intel Core i3 4005U CPU@ 1.70 GHz, può dipendere da ciò?? Grazie e spero di essere stato chiaro. Il codice per provare è nella prima domanda, è breve. Grazie.
  • Re: Mi fate questo calcolo, mi si blocca la compilazione!!

    La Ram non c'entra nulla.

    Usa i double per avere più cifre significative e, come ti è stato detto, non confrontare i valori float/double tra loro ... leggi quello che ti è stato scritto da @migliorabile, altrimenti perché cerchi suggerimenti qui?
  • Re: Mi fate questo calcolo, mi si blocca la compilazione!!

    oregon ha scritto:


    La Ram non c'entra nulla.

    Usa i double per avere più cifre significative e, come ti è stato detto, non confrontare i valori float/double tra loro ... leggi quello che ti è stato scritto da @migliorabile, altrimenti perché cerchi suggerimenti qui?
    Non ho capito molto bene questo:
    Invece di usare x == y oppure x != y DEVI usare abs(x-y) <= eps oppure abs(x-y) > eps

    per un qualche eps/ilon, numero piccolo.

    Ma anche il valore di eps NON PUO" ESSERE TROPPO PICCOLO, altrimenti la disuguaglianza potrebbe non verificarsi mai.

    Comunque la soluzione data dal mio libro (perchè io la soluzione non la vedo prima) è questa nel codice sotto: anche se il mio metodo del break sembra migliore ma invano se, come dice migliorabile, si tratta di una serie infinita e dunque agire con i limiti e gli epsiolon, solo che io lì ancora non ci sono ) ....
    
    // Esercizio 4.26 Soluzione
    #include <stdio.h>
    int main (void) {
      unsigned int accuracy = 400000; // imposta la precisione decimale
      printf( "Accuracy set at; %u\n", accuracy );
      // stampa le intestazioni di tabella
      puts( "term\t\t   pi" );
      double pi = 0.0; // valore approssimato per pi
      double num = 4.0; // numeratore
      double denom = 1.0; // denominatore del termine corrente
      // effettua una iterazione attraverso ciascun termine
      for (unsigned int loop = 1; loop <= accuracy; ++loop) {
        // se il termine è un numero dispari aggiungi il termine corrente
        if ( loop % 2 != 0 ) {
          pi += num/denom;
        } else { // se il termine è un numero pari sottrai il termine corrente
          pi -= num/denom;
      }
      // stampa il numero di termini e il valore approssimato
      // per pi con 6 cifre di precisione
      printf( "%u\t\t%lf\n", loop, pi );
      denom += 2.0; // aggiorna il denominatore
    }
    }
    
    https://prnt.sc/hduyw
Devi accedere o registrarti per scrivere nel forum
6 risposte