hilfdirselbst.ch
Facebook Twitter gamper-media
Aldemarin
Beiträge: 5
29. Aug 2013, 09:48
Beitrag #1 von 3
Bewertung:
(2945 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen

e und pi mit vielen Nachkommastellen berechnen


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)
Top
 
X
MurphysLaw
Beiträge: 588
29. Aug 2013, 11:25
Beitrag #2 von 3
Beitrag ID: #516796
Bewertung:
(2917 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen

e und pi mit vielen Nachkommastellen berechnen


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

;-)

________________________________________

Die letzte Stimme, die man hört, bevor die Welt explodiert, wird die Stimme eines Experten sein, der sagt: Das ist technisch unmöglich! (Sir Peter Ustinov)
als Antwort auf: [#516791] Top
 
Aldemarin
Beiträge: 5
9. Sep 2013, 17:53
Beitrag #3 von 3
Beitrag ID: #517090
Bewertung:
(2819 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen

e und pi mit vielen Nachkommastellen berechnen


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] Top