[GastForen Programmierung/Entwicklung PHP und MySQL e und pi mit vielen Nachkommastellen berechnen

  • Suche
  • Hilfe
  • Lesezeichen
  • Benutzerliste
Themen
Beiträge
Moderatoren
Letzter Beitrag

e und pi mit vielen Nachkommastellen berechnen

Aldemarin
Beiträge gesamt: 5

29. Aug 2013, 09:48
Beitrag # 1 von 3
Bewertung:
(4470 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Bestimmt hat schon einmal so mancher Programmierer mit der Idee gespielt, ein Programm zu schreiben, welches die transzendenten Zahlen e und pi auf mindestens mehrere dutzend Dezimalstellen genau zu berechnen. Doch leider ist dies nicht so leicht möglich, weil die Fließkommazahlenbereiche der üblichen Programmiersprachen eine beschränkte, festgelegte Genauigkeit haben.

Ein möglicher Ausweg aus diesem Dilemma besteht zum Beispiel darin, Zahlen als Zeichenketten zu behandeln und den Computer beizubringen mit diesen auf die gleiche Weise zu rechnen, wie man es in der Schule gelernt hat, als es noch keine Taschenrechner und Computer gab.

Die Beschränkung ist in diesem Fall durch die maximale Länge von Zeichenketten gegeben, welche sich von Programmiersprache zu Programmiersprache unterscheidet, aber bei modernen Programmiersprachen in der Regel höher ist als die größten standardmäßig verarbeitbaren Fließkommazahlen .

Allerdings hat diese Methode zu rechnen eine sehr schlechte Performance, die zu langen Programmlaufzeiten führt, was aber bei der Bestimmung von irrationalen Zahlen mit hoher Genauigkeit nur von geringer Bedeutung ist. Im Folgenden ist ein php-Programm publiziert, welches nach dieser Methode die Zahlen e und pi mit höchster Genauigkeit berechnen kann, wobei als Grundlage für die Berechnung von pi die Formel 16 * arctan(1/5)-4*arctan(1/239) dient und für die Berechnung von e die Summe der Kehrwerte der Fakultäten.

Hier der Code

<?php
$Wunschzahl = "e";


if ($Wunschzahl === "pi")
{
//$e = E_Wert();
$Schrittzahl = 100;
$Schrittzahl1 = ceil(4 + $Schrittzahl* (log(5))/(log(239)));
$Schrittzahl2 = ceil(0.75 * $Schrittzahl);
$pi = Pi_Wert ( $Schrittzahl, $Schrittzahl1, $Schrittzahl2);
//echo $e."\n ";
echo "Berechnung von pi\n\n pi = ".$pi."\n auf ".(string)($Schrittzahl2 - 2). " Nachkommastellen genau berechnet.\n\n\n\nSchrittzahlen\n\nArkustangens 1/5 mit ".$Schrittzahl." Schritten berechnet.\nArkustangens 1/239 mit ".$Schrittzahl1." Schritten berechnet.\nDivision mit ".$Schrittzahl2." Schritten berechnet.";
echo"\n\n";
}
if ($Wunschzahl === "e")
{
$Schrittzahl = 250;
$Schrittzahl1 = ceil(0.75 * $Schrittzahl);
$Schrittzahl1 = 202;
$e = E_Wert( $Schrittzahl, $Schrittzahl1);
echo "Berechnung von e\n\n e = ".$e."\n auf ".(string)($Schrittzahl1 - 2). " Nachkommastellen genau berechnet.\n\n\n\nSchrittzahlen\n\nKehrwerte Fakultätsreihe mit ".$Schrittzahl." Schritten berechnet.\nDivision mit ".$Schrittzahl1." Schritten berechnet.";
echo"\n\n";
}
?>
<?php
function Stradd ($a, $b )
//Addition von 2 Zahlen als String, ermöglicht Addition beliebig grosser Zahlen
{

$a = str_replace(",",".",$a);
$b = str_replace(",",".",$b);

if (strpos($a,".") == false)
{
$a1 =$a;
$a2 = "0";
}
else
{
$a1 = substr($a,0,strpos($a,"."));
$a2 = substr($a,1 + strpos($a,"."));
}

if (strpos($b,".") == false)
{
$b1 =$b;
$b2 = "0";
}
else
{
$b1 = substr($b,0,strpos($b,"."));
$b2 = substr($b,1 + strpos($b,"."));
}



while (strlen($a1) < strlen($b1))
{
$a1 = "0".$a1;
}

while (strlen($b1) < strlen($a1))
{
$b1 = "0".$b1;
}

$a1 ="0".$a1;
$b1 ="0".$b1;


while (strlen($a2) < strlen($b2))
{
$a2 = $a2."0";
}

while (strlen($b2) < strlen($a2))
{
$b2 = $b2."0";
}
$a = $a1.".".$a2;
$b = $b1.".".$b2;

//echo $a. "$".$b."X\n";


$i = 0;
$u = 0;
$d ="";
while ($i < strlen($a))
{
$i = $i + 1;
$c1 = substr($a,strlen($a) - $i,1);
$c2 = substr($b,strlen($b) - $i,1);
if ($c1 == ".")
{
$d = $d.".";
}
else
{
$d = $d.( string )(($c1 + $c2 + $u) %10);

$u = ( int )(($c1 + $c2 + $u) / 10.0);
}


//echo $c1;
}
$d = strrev($d);
while (substr($d,0,1) == "0")
{
$d = substr($d,1);

}
//echo "\n".$d."\n";
return $d;
}
?>


<?php
function Strsub ($a, $b )
//Subtraktion von 2 Zahlen als String, ermöglicht Subtraktion beliebig grosser Zahlen
{

$a = str_replace(",",".",$a);
$b = str_replace(",",".",$b);

if (strpos($a,".") == false)
{
$a1 =$a;
$a2 = "0";
}
else
{
$a1 = substr($a,0,strpos($a,"."));
$a2 = substr($a,1 + strpos($a,"."));
}

if (strpos($b,".") == false)
{
$b1 =$b;
$b2 = "0";
}
else
{
$b1 = substr($b,0,strpos($b,"."));
$b2 = substr($b,1 + strpos($b,"."));
}



while (strlen($a1) < strlen($b1))
{
$a1 = "0".$a1;
}

while (strlen($b1) < strlen($a1))
{
$b1 = "0".$b1;
}

$a1 ="0".$a1;
$b1 ="0".$b1;


while (strlen($a2) < strlen($b2))
{
$a2 = $a2."0";
}

while (strlen($b2) < strlen($a2))
{
$b2 = $b2."0";
}
$a = $a1.".".$a2;
$b = $b1.".".$b2;


$i = 0;
$u = 0;
$d ="";

while ($i < strlen($a))
{
$c1 = (int)substr($a,$i,1);
$c2 = (int)substr($b,$i,1);
if ($c2 == $c1)
{
$i = $i + 1;
}
else
{
$i = strlen($a);
if ($c2 > $c1)
{
$i = strlen($a);
$tauschen = true;
}
else
{
$i = strlen($a);
$tauschen = false;
}
}
}

if ($tauschen === true)
{
$H = $b;
$b = $a;
$a = $H;
}
//echo $a. "$".$b."X\n";


$i = 0;
$u = 0;
$d ="";
while ($i < strlen($a))
{
$i = $i + 1;
$c1 = substr($a,strlen($a) - $i,1);
$c2 = substr($b,strlen($b) - $i,1);
if ($c1 == ".")
{
$d = $d.".";
}
else
{
if (($c1 - $c2 - $u) < 0)
{
$d = $d.( string )($c1 - $c2 - $u + 10);
$u = 1;
}
else
{
$d = $d.( string )($c1 - $c2 - $u);
$u = 0;
}

}


//echo $c1;
}
$d = strrev($d);
while (substr($d,0,1) == "0")
{
$d = substr($d,1);

}

if($tauschen === true)
{
$d = "-".$d;
}
//echo "\n".$d."\n";
return $d;
}
?>


<?php
function Strmult ($a, $b )
//Multiplikation von 2 Zahlen als String, ermöglicht Multiplikation beliebig grosser Zahlen
{

$a = str_replace(",",".",$a);
$b = str_replace(",",".",$b);

if (stripos($a,".") === FALSE)
{
$Dezimalzahl_a = 0;
}
else
{
$Dezimalzahl_a = strlen($a) - stripos($a,".") - 1;
}

if (stripos($b,".") === FALSE)
{
$Dezimalzahl_b = 0;
}
else
{
$Dezimalzahl_b = strlen($b) - stripos($b,".") - 1;
}

$Dezimalzahl_Ergebnis = $Dezimalzahl_a + $Dezimalzahl_b;

//echo "Dezimalen von a:".$Dezimalzahl_a."\n";

$a = str_replace(".","",$a);
$b = str_replace(".","",$b);

$Laenge = strlen($b);


//echo $a. "$".$b."X\n";

$k = 0;
while ($k < strlen($b))
{
$i = 0;
$u = 0;
$d[$k] ="";
$c2 = substr($b,strlen($b) - $k - 1,1);
while ($i < strlen($a))
{
$i = $i + 1;
$c1 = substr($a,strlen($a) - $i,1);
if ($i == strlen($a))
{
$d[$k] = $d[$k].(strrev(( string )($c1 * $c2 + $u)));
//echo "\nh".$d[$k].( string )($c1 * $c2 + $u)."\n";
}
else
{
if ($c1 == ".")
{
$d[$k] = $d[$k].".";
}
else
{
$d[$k] = $d[$k].( string )(($c1 * $c2 + $u) %10);
//echo "\nt".$d[$k]."\n";

$u = ( int )(($c1 * $c2 + $u) / 10.0);
}
}
//echo $c1;
}
$d[$k] = strrev($d[$k]);
$k = $k + 1;

}
$k = strlen($b) - 1;
while ($k > -1)
{
$k2 = $k;
$M = $d[$k];
while ($k2 > 0)
{
$M = $M."0";
$k2 = $k2 - 1;
}
$d[$k] = $M;
//echo "\n".$d[$k]."k=".$k."\n";
$k = $k - 1;
}


$k = 0;
while ($k < $Laenge)
{
while (strlen($d[$k])< strlen($d[$Laenge - 1]))
{
$d[$k] = "0".($d[$k]);
}
//echo "M=".$d[$k]."K=".$k." Länge=".$Laenge;
$k = $k +1;
}

$i = 0;
//echo "R".$b;
$i = 0;
$uebertrag = 0;
$Ergebnis = "";
while ($i < strlen($d[0]))
{
$k = 0;
$c2 = 0;
while ($k < strlen($b))
{
$c2 = $c2 + (int)(substr($d[$k],strlen($d[$k]) - $i - 1,1));
//echo "\n k=".$k.": ".$c2."\n";
$k = $k +1;
}
$c2 = $c2 + $uebertrag;
$uebertrag = ( int )($c2 / 10.0);
if ($i == -1 + strlen($d[0]))
{
$Ergebnis = $Ergebnis.strrev( ( string )($c2));
//echo "c2=".$c2." k=".$i. " Ergebnis =".$Ergebnis." Übertrag =".$uebertrag;
}
else
{
$Ergebnis = $Ergebnis.( string )($c2 %10);
//echo "C2=".$c2." k=".$i. " Ergebnis =".$Ergebnis." Übertrag =".$uebertrag;
}
$i = $i + 1;
}
$Ergebnis = strrev($Ergebnis);

$Kommastelle = strlen($Ergebnis) - $Dezimalzahl_a - $Dezimalzahl_b;

$Ergebnis = substr($Ergebnis,0,$Kommastelle).",".substr($Ergebnis,$Kommastelle);
return $Ergebnis;
//echo "c2final=".$c2." k=".$i. " Ergebnis =".$Ergebnis;


}
?>


<?php
function Strdiv ($a, $b, $Schrittzahl )
//Subtraktion von 2 Zahlen als String, ermöglicht Subtraktion beliebig grosser Zahlen
{
//$Schrittzahl = 60; //Legt die Zahl der Schritte fest. Darf verändert werden!
$a = str_replace(",",".",$a);
$b = str_replace(",",".",$b);

if (stripos($a,".") === FALSE)
{
$Dezimalzahl_a = 0;
}
else
{
$Dezimalzahl_a = strlen($a) - stripos($a,".") - 1;
}

if (stripos($b,".") === FALSE)
{
$Dezimalzahl_b = 0;
}
else
{
$Dezimalzahl_b = strlen($b) - stripos($b,".") - 1;
}

while ($Dezimalzahl_a < $Dezimalzahl_b)
{
$a = $a."0";
$Dezimalzahl_a = $Dezimalzahl_a + 1;
}

while ($Dezimalzahl_b < $Dezimalzahl_a)
{
$b = $b."0";
$Dezimalzahl_b = $Dezimalzahl_b + 1;
}

$a = str_replace(".","",$a);
$b = str_replace(".","",$b);

$a = ltrim($a,"0");
$b = ltrim($b,"0");

//echo "a =".$a." b=".$b."\n\n";

$Ergebnis ="";
$i = 0;
$Komma ="";
while (strlen($a) < strlen($b))
{
$a = $a."0";
if ($i === 0)
{
$Ergebnis =$Ergebnis."0,";
$Komma = "J";
}
else
{
$Ergebnis =$Ergebnis."0";
}
$i = $i + 1;
}

$a2 = substr($a,0,strlen($b));
$k = 0; //Zähler für noch zu realisierende äussere Schleife


while ($k < $Schrittzahl)
{
//echo "b =".$b." a2=".$a2;
$j = 0;
$stop = 0;
while ($stop == 0)
{
//Grössenvergleich
$i = 0;
while (strlen($b) < strlen($a2))
{
$b = "0".$b;
}
while ($i < strlen($a2))
{
$c1 = (int)substr($a2,$i,1);
$c2 = (int)substr($b,$i,1);
if ($c2 == $c1)
{
$i = $i + 1;
}
else
{
$i = strlen($a2);
if ($c2 > $c1)
{
$i = strlen($a2);
$stop = 1;
}
else
{
$i = strlen($a2);
$stop = 0;
}
}
}
//echo "Stop =".$stop;
// Subtraktion

if ($stop == 0)
{
$i = 0;
$u = 0;
$d ="";
while ($i < strlen($a2))
{
$i = $i + 1;
$c1 = substr($a2,strlen($a2) - $i,1);
$c2 = substr($b,strlen($b) - $i,1);
if ($c1 == ".")
{
$d = $d.".";
}
else
{
if (($c1 - $c2 - $u) < 0)
{
$d = $d.( string )($c1 - $c2 - $u + 10);
$u = 1;
}
else
{
$d = $d.( string )($c1 - $c2 - $u);
$u = 0;
}

}


//echo $c1;
}
$d = strrev($d);
//echo "d = ".$d;
$j = $j + 1;
}
else
{
$d = $a2;
}
$a2 = $d;
//echo "j =".$j." a2(else von if (stop == 0)=".$a2;
//$stop = 1;
}
$a2 = ltrim($a2,"0");
$b = ltrim($b,"0");
//echo "Getrimmtes a2 =".$a2;
if ($a2 == "")
{
$a2 = "0";
}

//echo "j =".$j." a2=".$a2;
if ((strlen($a)) > ($k + strlen($b)))
{
$a2 = $a2.substr($a, $k + strlen($b),1);
}
else
{
$a2 = $a2."0";
}
//echo " a2( nach Übertrag)) =".$a2;
//echo " j =".$j." a2=".$a;
if (((strlen($a)) === (-1 + $k + strlen($b))) and ($Komma ===""))
{
$Ergebnis = $Ergebnis.",".$j;
}
else
{
$Ergebnis = $Ergebnis.$j;
}
$k = $k + 1;
}//Ende while ( k<)
$Ergebnis = ltrim($Ergebnis,"0");
if (substr($Ergebnis,0,1) ===",")
{
$Ergebnis = "0".$Ergebnis;
}
//echo "Ergebnis = ".$Ergebnis;
return $Ergebnis;
}
?>
<?php
function Arcustangens ($a, $b)
{
$k = 0;
$a3 = "0";
$b3 = "1";
$Schrittzahl = 10; //Legt die Zahl der Schritte fest. Darf verändert werden
while ( $k < $Schrittzahl)
{
$j = 0;
$a2 = "1";
$b2 = "1";
while ($j < (2*$k +1))
{
//$a2 = $a2 * $a;
$a2 = Strmult($a2,$a);
//$b2 = $b2*$b;
$b2 = Strmult($b2,$b);
$j = $j + 1;
}
//$b2 = $b2*(2*$k +1);
$b2 = Strmult($b2, (string)(2*$k +1));

if (($k % 2) === 1)
{
$a3 =Strsub(Strmult($a3,$b2),Strmult($a2,$b3));
//$a3 = $a3*$b2 - $a2*$b3;
//$b3 = $b2 * $b3;
$b3 = Strmult($b2,$b3);
}
else
{
$a3 =Stradd(Strmult($a3,$b2),Strmult($a2,$b3));
//$a3 = $a3*$b2 + $a2*$b3;
//$b3 = $b2 * $b3;
$b3 = Strmult($b2,$b3);
}

$k = $k + 1;
}
echo $a3."/".$b3;
Strdiv ($a3, $b3 );

}
?>
<?php
function Pi_Wert ($Schrittzahl, $Schrittzahl1, $Schrittzahl2)
{
$a = "1";
$b= "5";
$k = 0;
$a3 = "0";
$b3 = "1";
$Schrittzahl = 100; //Legt die Zahl der Schritte fest. Darf verändert werden!
while ( $k < $Schrittzahl)
{
$j = 0;
$a2 = "1";
$b2 = "1";
while ($j < (2*$k +1))
{
//$a2 = $a2 * $a;
$a2 = Strmult($a2,$a);
//$b2 = $b2*$b;
$b2 = Strmult($b2,$b);
$j = $j + 1;
}
//$b2 = $b2*(2*$k +1);
$b2 = Strmult($b2, (string)(2*$k +1));

if (($k % 2) === 1)
{
$a3 =Strsub(Strmult($a3,$b2),Strmult($a2,$b3));
//$a3 = $a3*$b2 - $a2*$b3;
//$b3 = $b2 * $b3;
$b3 = Strmult($b2,$b3);
}
else
{
$a3 =Stradd(Strmult($a3,$b2),Strmult($a2,$b3));
//$a3 = $a3*$b2 + $a2*$b3;
//$b3 = $b2 * $b3;
$b3 = Strmult($b2,$b3);
}

$k = $k + 1;
}
//echo $a3."/".$b3;
//Strdiv ($a3, $b3 );
$a4 = Strmult("16",$a3);
$b4 = $b3;


$a = "1";
$b= "239";
$k = 0;
$a3 = "0";
$b3 = "1";
while ( $k < $Schrittzahl1)
{
$j = 0;
$a2 = "1";
$b2 = "1";
while ($j < (2*$k +1))
{
//$a2 = $a2 * $a;
$a2 = Strmult($a2,$a);
//$b2 = $b2*$b;
$b2 = Strmult($b2,$b);
$j = $j + 1;
}
//$b2 = $b2*(2*$k +1);
$b2 = Strmult($b2, (string)(2*$k +1));

if (($k % 2) === 1)
{
$a3 =Strsub(Strmult($a3,$b2),Strmult($a2,$b3));
//$a3 = $a3*$b2 - $a2*$b3;
//$b3 = $b2 * $b3;
$b3 = Strmult($b2,$b3);
}
else
{
$a3 =Stradd(Strmult($a3,$b2),Strmult($a2,$b3));
//$a3 = $a3*$b2 + $a2*$b3;
//$b3 = $b2 * $b3;
$b3 = Strmult($b2,$b3);
}

$k = $k + 1;
}
//echo $a3."/".$b3;
//Strdiv ($a3, $b3 );

$a3 = Strmult("4",$a3);

$a4 =Strsub(Strmult($a4,$b3),Strmult($a3,$b4));
$b4 =Strmult($b3,$b4);
return(Strdiv ($a4, $b4, $Schrittzahl2 ));
//echo $a3."/".$b3;
//Strdiv ($a3, $b3 );

}
?>
<?php
function E_Wert( $Grenzwert, $Schrittzahl1)
{

$a = "1";
$k = 0;
$b = "1";
$c = "1";
$d = "1";
while ($k < ($Grenzwert + 1))
{
$j = 1;
$f = "1";
while ($j < ($k + 2))
{

//$f = $f*$j;
$f = Strmult($f, (string)$j);
$j = $j + 1;
}

//$b =$b*$f + $c*$d;
$b = Stradd((Strmult($b,$f)),Strmult($c,$d));
//$c = $c*$f;
$c = Strmult($c,$f);
$k = $k + 1;
}
return (Strdiv($b,$c, $Schrittzahl1));
}
?>

Programmbeispiel

Berechnung von pi

pi = 3,14159265358979323846264338327950288419716939937510582097494459230781
auf 68 Nachkommastellen genau berechnet.



Schrittzahlen

Arkustangens 1/5 mit 100 Schritten berechnet.
Arkustangens 1/239 mit 34 Schritten berechnet.
Division mit 70 Schritten berechnet.

Programmlaufzeit: 3h31m52s

(Dieser Beitrag wurde von Aldemarin am 29. Aug 2013, 09:50 geändert)
X

e und pi mit vielen Nachkommastellen berechnen

MurphysLaw
Beiträge gesamt: 588

29. Aug 2013, 11:25
Beitrag # 2 von 3
Beitrag ID: #516796
Bewertung:
(4442 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Zitat Bestimmt hat schon einmal so mancher Programmierer mit der Idee gespielt, ein Programm zu schreiben, welches die transzendenten Zahlen e und pi auf mindestens mehrere dutzend Dezimalstellen genau zu berechnen.


Ja, klar. Aber:
Zitat Programmlaufzeit: 3h31m52s


Das erinnert mich an BASIC auf meinen C64. o_O

Für solche Aufgaben nehme ich dann doch lieber eine echte Programmiersprache (C++ oder C#) und mach sowas nicht in PHP - und erst Recht nicht durch die Brust ins Auge. :-P

In C# sind Math.Pi und Math.e übrigens hinreichend genau zur Berechnung. Wenns nur ums Anzeigen geht:
Schau mal diesen rekursiven Algorithmus hier:
http://stackoverflow.com/questions/39395/how-do-i-calculate-pi-in-c

oder dieses kleine Progrämmchen:
http://www.codeproject.com/Articles/11692/Calculate-pi-to-one-million-decimal-places

;-)


als Antwort auf: [#516791]

e und pi mit vielen Nachkommastellen berechnen

Aldemarin
Beiträge gesamt: 5

9. Sep 2013, 17:53
Beitrag # 3 von 3
Beitrag ID: #517090
Bewertung:
(4344 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Noch ein Nachkplapp zur Berechnung von e:

Berechnung von e

e = 2,71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901
auf 200 Nachkommastellen genau berechnet.



Schrittzahlen

Kehrwerte Fakultätsreihe mit 250 Schritten berechnet.
Division mit 202 Schritten berechnet.

Programmlaufzeit: 2h56m6s


als Antwort auf: [#516796]