Problem mit Datentyp "NULL" |
Pirroh
Otto Normalposter
Dabei seit: 10.10.2004
Beiträge: 110
Herkunft: Breskens / Niederlande
Level: 35 [?]
Erfahrungspunkte: 785.885
Nächster Level: 824.290
|
|
Problem mit Datentyp "NULL" |
|
Ich habe ein kleines PHP-Prog geschrieben, was mir die Fakultät einer möglichst hohen Zahl ausrechnen soll. Im Grunde ist das Programm schon fertig. Aber die Variable $i ist aus mir unbegreiflichen Gründen immer vom Datentyp "NULL". Mir will nicht in den Kopf, wie das zustandekommt. Ich hoffe ihr könnt mir helfen.
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
|
<html>
<head>
<title>
</title>
</head>
<body bgcolor='#f0f0f0'>
<?php
$i=$_POST['grossezahl'];
if($i=='0')
$i='1';
$date_vor=date("H.i.s");
$zahl=fakultaet('1','0',$i);
print "
<form action='index.php' method='POST'>
<input type='text' name='grossezahl' value='$i'>
<input type='submit' value='Berechnen'>
</form>
".$date_vor."<br>".date('H.i.s')."<br><br>Die Fakultät von ".($i)." ist (".strlen($zahl)." Stellen):<br><br>".wordwrap($zahl,50,"<br>",true)."
";
function fakultaet($zahl2,$jz,$iz){
if($jz!=$iz){
++$jz;
fakultaet(bcmul($zahl2,$jz),$jz,$iz);
}
return $zahl2;
}
?>
</body>
</html> |
|
|
|
25.11.2005 21:06 |
|
|
MoD3000
Hoffnungsloser Fall
Dabei seit: 25.09.2002
Beiträge: 3.510
Level: 56 [?]
Erfahrungspunkte: 27.694.012
Nächster Level: 30.430.899
|
|
Ich hätte glatt darauf getippt, dass du $i am Anfang NULL gesetzt bekommst, weil nicht existent. Teste vor der Zuweisung. Nach dem Submit hat $i dann regulär den Wert NULL übernommen.
Wie sieht dein Code jetzt aus?
|
|
25.11.2005 23:51 |
|
|
Pirroh
Otto Normalposter
Dabei seit: 10.10.2004
Beiträge: 110
Herkunft: Breskens / Niederlande
Level: 35 [?]
Erfahrungspunkte: 785.885
Nächster Level: 824.290
|
|
Ich hatte die Fakultätenrechnung vorher auch mit einer for-Schleife gemacht, da hab ich für 50000! 4min 48 sek gebraucht. Und jetzt zweifle ich noch ein weiteres mal an mir. Nur noch die Fakultät bis genau 19381 berechnet er. Alles was rüber ist macht er einfach nciht, soll heissen $i ist in diesem Fall leer. Aber wenn das schon so ist, warum dann gerade bei der 19381?
hmm. Auf jeden fall funktioniert das proc erstmal
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
|
<html>
<head>
<title>
</title>
</head>
<body bgcolor='#f3f3f3'>
<?php
function fakultaet($zahl) {
if ($zahl==0) return '1';
return bcmul($zahl,fakultaet($zahl - '1'));
}
$i=$_POST['zahl'];
if($i=='0')
$i='1';
$date_vor=date("H.i.s");
$zahl=fakultaet($i);
print "
<form action='index.php' method='POST'>
<input type='text' name='zahl' value='$i'>
<input type='submit' value='Berechnen'>
</form>
".$date_vor."<br>".date('H.i.s')."<br><br>
Die Fakultät von ".($i)." ist (".strlen($zahl)." Stellen)<br><br>".wordwrap($zahl,50,"<br>",true)
;
?>
</body>
</html> |
|
|
|
26.11.2005 00:14 |
|
|
MoD3000
Hoffnungsloser Fall
Dabei seit: 25.09.2002
Beiträge: 3.510
Level: 56 [?]
Erfahrungspunkte: 27.694.012
Nächster Level: 30.430.899
|
|
Du verbrauchst mit der Loesung einiges an Stack, was hast du php denn als Speicherwert erlaubt und wie lange darf das Ding rechnen?
|
|
26.11.2005 10:03 |
|
|
stanny
Forenwächter
Dabei seit: 21.09.2002
Beiträge: 2.075
Herkunft: Lüneburg
Level: 53 [?]
Erfahrungspunkte: 16.381.306
Nächster Level: 19.059.430
|
|
Ich finde die Abfrage ein wenig komisch. Warum ueberhaupt das $i und warum wird in deiner Funktion ein explizites Ergebnis fuer $i == 0 ausgegeben, wenn $i == 0 niemals true sein wird?
Ich wuerde es so machen:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
|
<?php
function fakultaet($zahl) {
return bcmul($zahl,bcmul($zahl-1));
}
if ($_POST['submit']) {
echo 'Die Fakultaet blablabla '.$zahl.' blablabla '.fakultaet($zahl).';
}
echo '<form method="post" action="?">';
echo ' <input type="text" name="zahl" value="1">';
echo ' <input type="submit" name="submit" value="Berechnen">';
echo '</form>';
?>
|
|
Allerdings nicht getestet und btw. warum rufst du binner der Funktion fakultaet die Funktion fakultaet auf... geht das ueberhaupt?
__________________ theharlekin.de
|
|
26.11.2005 10:07 |
|
|
Ben
Hirngeschädigter
Dabei seit: 26.09.2005
Beiträge: 665
Level: 45 [?]
Erfahrungspunkte: 4.517.920
Nächster Level: 5.107.448
|
|
Das "in einer Funktion die Funktion selbst aufrufen" bezeichnet man als Rekursion. Es sollte generell in jeder modernen Programmiersprache funktionieren. Du brauchst für eine Rekursion generell zwei Dinge:
1. Eine Rechenanweisung, mit der du von "n" auf "n - 1" kommst. Das wäre hier (sinngemäß) fak(n)= n*fak(n-1)
2. Eine Endbedingung, die einen konkreten Wert liefert: if (n==0) {return 1}
Die Berechnung von fak(4) sieht dann z.B. so aus:
fak(4) = 4*fak(4-1) = 4* fak(3) = 4*3*fak(3-1) = 4*3*fak(2) = 4*3*2*fak(2-1) = 4*3*2*fak(1) = 4*3*2*1*fak(1-1) = 4*3*2*1*fak(0) = 4*3*2*1*1 = 24 da wir fak(0) durch unsere Endbedingung als 1 definiert haben.
Man sieht, dass z.B. fak(900) ein extrem langer Ausdruck würde. Hier hängt es von den Fähigkeiten der jeweiligen Programmiersprache ab, wie gut (=speicherschonend) Zwischenergebnisse gebildet werden.
Die Ausdrücke werden aber ohnehin extrem groß, da die Fakultätsfunktion sehr steil ansteigt.
Mein Taschenrechner schafft nur noch fak(69)=1,7E98
Irgendwann werden die Zahlen auch für deinen Computer zu groß, als dass er sie speichern kann.
Ich würd mich mal informieren, wie genau die Zahlen im Computer gespeichert werden.
positive 32bit Integer z.B. können maximal 2^32=4E9 groß sein. Bei floats wird meine ich die Hälfte für die Mantisse und die andere Hälfte für den Exponenten verwendet. Für 32bit hieße das, dass du nach der Rechnung von eben ca 9 Stellen für die Zahl selbst und nochmal 9 für den Exponenten hast. Es sei denn, die Floats haben auch ein Vorzeichen, da geht dann natürlich nochmal ein bit für drauf. Dürfte aber nicht wirklich viel ändern...
Ich hab mir die ganze Sache mal mit Python reingezogen. Ich habe folgende Funktion verwendet (Wikipedia, wäre aber auch nicht schwer selbst zu schreiben):
def factorial(x):
if x == 0:
return 1
else:
return x * factorial(x - 1)
Macht im Prinzip das selbe wie die PHP-Funktion auch. Mit der hier kann man das Ergebnis bis factorial(998) berechnen, das geht dann so schnell, dass keine Verzögerung wahrnehmbar ist.
Ab factorial(999) flennt das Teil, dass ihm die Rekursion zu extrem wäre
Generell sollte die Rechenzeit mit der eingesetzten Zahl linear ansteigen (sagen wir mal, es wären für 1000 0,5s, dann wäre es für 2000 eben 1s usw. Der Speicherhunger sollte ebenfalls linear ansteigen. Wenn wir von 256MB freiem Arbeitsspeicher und einem Speicherbedarf von 64 bit pro Zahl ausgehen, dann wären das 256000000/8=32Mio. Man sollte also noch die Fakultät von 32Mio ausrechnen können. Nur wäre das Ergebnis wohl längst nicht mehr als 32 oder 64 bit Fließkommazahl darstellbar. Die Rechenzeit sollte dann 32Mio/2000=16000s=267min=knapp 5 Stunden sein.
__________________ Greatness, at any cost.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Ben: 26.11.2005 12:01.
|
|
26.11.2005 11:25 |
|
|
Pirroh
Otto Normalposter
Dabei seit: 10.10.2004
Beiträge: 110
Herkunft: Breskens / Niederlande
Level: 35 [?]
Erfahrungspunkte: 785.885
Nächster Level: 824.290
|
|
Ich berechne die Fakultät mit der PHP Funktion bcmul(). Das erlaubt mir beliebig lange Zahlen zu multiplizieren. Als Übergabeparameter will sie strings und keine Integer oder Float. Und sie gibt auch einen string zurück. Wirklich sehr praktisch das Teil
.
MOD3000
Zitat: |
Du verbrauchst mit der Loesung einiges an Stack, was hast du php denn als Speicherwert erlaubt und wie lange darf das Ding rechnen? |
|
Erlaubter Speicher ist 8 MB und zeit hat es 5 min. Wenn ich eine Zahl größer 19381 nehme dann braucht es nur 1 sek um wieder abzubrechen und es passiert gar nix. Und wenn ich die 19381 nehme dann dauert es 12 sek und ich habe sie.
Die Fakultät von 19380 ist (74675 Stellen)
67892939877216969015997428779710897260745295869267
62056607476375442016020836000374903551252445467575
61172346337089938558482459627074196290043323665245
40983594101066676801130614599812932838098499218392
27448433669673282332913559496238551983923953632723
26496612203997336590629422456343408456545208311458
45338445333711475059751071431811667215134648591320
68910278659446096747416736154840835748618543175600
79809905107124197435941265868717167515598930530571
03955625229387085321700004249700736817698783782774
34735540699781658885516290970244738408118361071169
20812676473652699795320491701115787691407995228869[.........]
@stanny: Ich nehme zwei verschiedene Variablen, um zwischen der Ein- und Ausgabe unterscheiden zu können.
|
|
26.11.2005 13:03 |
|
|
|