Clanintern Clanintern Clanintern

Forum

Öffentliche Foren
FORUM: Spiele & Computer THEMA: [PHP] Fakultät berechnen - ab 22 falsch
AUTOR BEITRAG
Ged

RANG Prophet of Clanintern

#1 - 19.05 14:14

ich habe mir ein kleines Script gebastelt, um eine Fakultät zu berechnen:

code:
function getFaculty ( $intN ) {

   $zaehli = 1;
   $produkt = 1;

   while ($zaehli <= $intN) {
   $produkt = $produkt * $zaehli;
   $zaehli++;
   }
   return $produkt;

   }


nun ist es aber so, daß ab 22 ein falscher Wert berechnet wird (ich habe hier mit dem Windows Taschenrechner verglichen)

Script:
1124000727777607600000

Taschenrechner:
1124000727777607800000

woran könnte das liegen?
ist der Taschenrechner verkehrt?
Kommt PHP mit diesen großen Zahlen nicht zurecht?


hier zum ausprobieren:
geddym.dyndns.org/treasure_grid.php

ich hab auch mal danach gegoogled, andere methode beim script:
code:
function facultaet($zahl)
   {
    if($zahl < 2){ return 1; }
       else { return facultaet($zahl - 1) * $zahl ;}
}


aber der gleiche fehler
kennt jemand dieses Phänomen?
*al!ve* - will code for food

RANG Master of Clanintern

#2 - 19.05 14:45

Bring mal in Erfahrung, wie lang deine Ints sein dürfen. Hier ne Grenze zu vermuten wär zwar dämlich weil deine Zahl etwas kleiner als 2^70 ist, aber deutlich weiter als nur läppische 200'000 von 2^70 entfernt. Trotzdem solltest du in etwa wissen, wie groß deine Zahlen sein können. So einfach aus gute drauf los nen Integer von mehr als 18446744073709551616 (2^64) anzunehmen ist schon sehr verwegen. Schon größere Zahlen als 4294967296 (2^32) sollten im Einzelfall geprüft werden.

Den Windowstaschenrechner kann man hier nicht als Referenz nehmen, der rechnet dir in deutlich höherer Genauigkeit als das Betriebssystem das unterstützt. Dem kann ich auch 1000000! rechnen lassen. Der ploppt zwar alle 30 Sekunden mit "kann noch n Weilchen dauern" auf aber er zieht s durch.
vaest´ark // patrick *circle of confusion*

RANG Master of Clanintern

#3 - 19.05 14:57

ich hatte damals schon probleme mit 2^32. 2^31 war noch richtig, 2^32 ergab -1. ich denke, das liegt daran das php nur signed-int verwenden wollte. hab mich nicht näher drum gekümmert und ne grenze bei max 2^31 eingebaut (so hohe zahlen brauchte ich eh nicht).
das problem trat im zusammenhang mit dem bitshifting auf (1 << 32).
Ged

RANG Prophet of Clanintern

#4 - 19.05 15:24

wenns denn tatsächlich am integer klemmen würde:
wie kann ich diese begrenzung umgehen?
gibts andere variablentypen (longint, double) wie in C?

quote:
Den Windowstaschenrechner kann man hier nicht als Referenz nehmen, der rechnet dir in deutlich höherer Genauigkeit als das Betriebssystem das unterstützt.

also kann ich davon ausgehen, daß sein ergebnis stimmt?

am rande:
das script läuft auf nem debian etch - sind mir da irgendwie schon grenzen aufgelegt?
*al!ve* - will code for food

RANG Master of Clanintern

#5 - 19.05 16:27

de.php.net/integer
quote:
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.


PHP_INT_MAX hat bei mir einen Wert von 2147483647, also 2^31.

Du kannst mit floats rechnen. Das Floatformat ist zwar auch plattformabhängig, scheint aber zumindest deutlich mehr Raum zu haben. Auf php.net steht was vom 64Bit-IEEE-Format.

Und ja, beim Windows-Taschenrechner kannst du von richtigen Ergebnissen ausgehen. Hab ich damals auch verwendet, als ich schriftlich zwei 1024Bit-Ints multipliziert hab und anschließend mein Ergebnis prüfen wollte. RSA, El Gamal und was weiß ich was alles .

[edit]

de.php.net/manual/de/ref.bc.php
Das würde helfen.
Ged

RANG Prophet of Clanintern

#6 - 19.05 19:18

also mit bcmul hab ichs auch schon probiert - leider ohne erfolg:

code:

function facultaet($zahl)
   {
    if($zahl < 2){ return 1; }
       else { return bcmul(facultaet($zahl - 1),$zahl,100000);}
}

(beim dritten parameter isses egal, was für ne genauigkeit ich angebe)
*al!ve* - will code for food

RANG Master of Clanintern

#7 - 20.05 00:40

Öhm, nein. Es könnte natürlich sein, dass es gar nicht daran liegt. Aber du rechnest in #6 an deutlich zu wenigen Stellen mit der falschen Genauigkeit. Du musst da Strings nehmen, sonst kommen dir in den unteren Leveln trotzdem doubles oder ints raus.


PHP-code:
<?php 
function bcfacultaet($zahl) {
  
$zahl = (string) $zahl;
  
$precission 1000;
  if (
bccomp($zahl"2"$precission) === -1)
    return 
"1";
  else
    return 
bcmul(bcfacultaet(bcsub($zahl"1"$precission)), $zahl$precission);
}
 
?>
Ged

RANG Prophet of Clanintern

#8 - 27.05 12:47

besser spät als nie
danke!

ich dachte, daß bei bcxyz der inhalt einer variablen automatisch als string behandelt wird