Frage der Präzision? (pi, gmp)



  • Hi Volks!

    Ich hab' mir gestern und heute auch zufällig den Kopf über die Berechnung von pi zerbrochen und das Resultat meiner Bemühungen war die Erkenntnis:

    pi = 16 arctan(1/5) - 4 arctan(1/239)

    Danach hab' ich mir 'ne mp Library für C gesucht und bin auf GMP 4.1.2 gestoßen. Mein Problem ist jedoch, daß ab

    3,141592653589793        2384626433832795... // pi
    3,141592653589793 [hier] 4107032954041479... // 'mein' pi
    

    nicht's mehr stimmt.
    Ich denk mal, es liegt an der Prezision meiner variablen.

    Meine Fragen daher:

    Welche Prezision für C brauche ich, wenn C das Resultat einer Potenz (64 bit float)^(32 bit integer) ist?
    Welche Prezision für T brauche ich, wenn T das Resultat einer Division (Prezision C?) / (32 bit integer) ist?
    Welche Prezision für ArcTan brauch ich, wenn ArcTan das Resultat einer Addition (Prezision ArcTan?) / (Prezision T) ist?

    Vielleicht kann jemand licht in's Dunkel bringen.

    THXIA

    Swordfish



  • Welches arctan benutzt du denn?



  • mein eigenes!?

    arctan(x) definiert sich doch gerade durch

    x^3   x^5   x^7   x^9
      arctan(x) = x - --- + --- - --- + --- ...
                       3     5     7     9
    


  • Dann liegts evtl. an deiner Implementierung. Wie siehts aus wenn du ein paar mehr Iterationsschritte machst?

    Btw: Hat gmp keine eigene arctan Implementierung?



  • Ja, gmp müsst schon 'ne Implementierung dafür haben, aber das nutzt mir nichts wenn ich 16 arctan(1/5) - 4 arctan(1/239) beim konvergieren gegen pi zusehen möchte.

    Ich hab's mal so implementiert:

    dStartTime = GetTime();
    
    // make sure that strPi is different from strOldPi
    // ...preliminary code and topic to change ;)
    strPi[0] = 1;	strOldPi[0] = 2;
    strPi[1] = 0;	strOldPi[1] = 0;
    
    for(__int32 i = 0, z = 3; strcmp(strPi, strOldPi); i++, z += 2)
    {
      free(strPi);
      free(strOldPi);
    
      mpf_pow_ui(mpfC1, mpfX1, z);
      mpf_pow_ui(mpfC2, mpfX2, z);
      mpf_div_ui(mpfT1, mpfC1, z);
      mpf_div_ui(mpfT2, mpfC2, z);
    
      if(blnSign)
      {
        mpf_add(mpfArcTan1, mpfArcTan1, mpfT1);
        mpf_add(mpfArcTan2, mpfArcTan2, mpfT2);
      } else {
        mpf_sub(mpfArcTan1, mpfArcTan1, mpfT1);
        mpf_sub(mpfArcTan2, mpfArcTan2, mpfT2);			
      }
    
      blnSign = !blnSign;
    
      // Save old pi for comparison:
      strOldPi = mpf_get_str(NULL, &eExp, 10, LONG_MAX, mpfPi);
    
      mpf_mul_ui(mpfPP1, mpfArcTan1, 16);
      mpf_mul_ui(mpfPP2, mpfArcTan2, 4);
      mpf_sub(mpfPi, mpfPP1, mpfPP2);
    
      strPi = mpf_get_str(NULL, &eExp, 10, LONG_MAX, mpfPi);
    
      szPiLength     = strlen(strPi);
      szOldPiLength  = strlen(strOldPi);
      szOldLastPiPos = szLastPiPos;
    
      for(szLastPiPos = szOldLastPiPos; szLastPiPos < szPiLength && szLastPiPos < szOldPiLength; szLastPiPos++)
        if(strPi[szLastPiPos] != strOldPi[szLastPiPos]) break;
    
      if(szLastPiPos)
      {
        printf("New digits found: %i\n", szLastPiPos - szOldLastPiPos);
        for(p = szOldLastPiPos; p < szLastPiPos; p++)
        {
          printf("Digit %i: %c  Elapsed time: %.3f\n", p, strPi[p], GetTime()-dStartTime);
        }
      }
    }
    

Anmelden zum Antworten