Problem mit Datentyp "NULL"

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • 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]
      <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>[/php]
    • Keine Ahnung, mit PHP kenne ich mich leider nicht aus. Du könntest aber auf jeden Fall die Fakultätsfunktion eleganter gestalten. Wenn ich das richtig verstanden habe, multiplizierst du "von unten hoch" also z.B. 1*2*3 statt 3*2*1. Ich würde es einfacher machen (rekursiv, das sollte es in deinem Beispiel doch auch sein, oder?):

      function fakultaet($zahl) {
      if ($zahl==0) {return 1}
      else { return $zahl*fakultaet($zahl - 1)}
      }

      Hoffe einfach mal, dass dir das weiterhilft und dass der Code (so ähnlich) auch in PHP geht.
      Vielleicht erledigt das ja auch das Problem mit diesem seltsamen Datentyp.
      Ich kann jedenfalls nicht glauben, dass man für etwas so einfaches wie eine Fakultät dermaßen viele Funktionsparameter in einer modernen Programmiersprache braucht... :think:
      Greatness, at any cost.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Ben ()

    • 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]
      <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>[/php]
    • 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:

      PHP-Quellcode

      1. <?php
      2. function fakultaet($zahl) {
      3. return bcmul($zahl,bcmul($zahl-1));
      4. }
      5. if ($_POST['submit']) {
      6. echo 'Die Fakultaet blablabla '.$zahl.' blablabla '.fakultaet($zahl).';
      7. }
      8. echo '<form method="post" action="?">';
      9. echo ' <input type="text" name="zahl" value="1">';
      10. echo ' <input type="submit" name="submit" value="Berechnen">';
      11. echo '</form>';
      12. ?>
      Alles anzeigen


      Allerdings nicht getestet und btw. warum rufst du binner der Funktion fakultaet die Funktion fakultaet auf... geht das ueberhaupt?
      theharlekin.de
    • 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 :D
      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. :D
      Greatness, at any cost.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Ben ()

    • 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 :D.

      MOD3000
      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.