Alex Fechner: Rest Rechnung mit PhP ab 10 Stellen Fehler

Hallo liebe PhPler.

Ich habe folgendes Problem:
Ich habe eine Zeit in Sekunden die ich aus verschidenen Gründen nicht mit mktime umrechnen will. Darum wollte ich dieses Sekundenanzahl / 60 Teilen um die Stunden zu erhalten. Den rest dieser Rechnung wiederum / 60 für die Minuten und der Rest davon sind ja dann die Sekunden. Dabei ist mir aufgefallen, dass ab 10stelligen Zahlen die Funktion % nichtmehr Funktioniert. z.B:

$rest1 = 61 % 60;
echo $rest1;
gibt aus: "1"

wenn man nun über 10 stellen geht wie z.B. hier:

$rest2 = 10000000000 % 60;
echo $rest2;

wird ein negativer Wert, bei noch mehr zeichen sogar nurnohc "0" ausgegeben. Bitte um Hilfe. MFG

  1. Hi,

    Ich habe eine Zeit in Sekunden die ich aus verschidenen Gründen nicht mit mktime umrechnen will. Darum wollte ich dieses Sekundenanzahl / 60 Teilen um die Stunden zu erhalten. Den rest dieser Rechnung wiederum / 60 für die Minuten und der Rest davon sind ja dann die Sekunden. Dabei ist mir aufgefallen, dass ab 10stelligen Zahlen die Funktion % nichtmehr Funktioniert. z.B:

    Dir ist bekannt, daß numerische Datentypen nur innerhalb gewisser Grenzen funktionieren?
    Bei integer meist zwischen -2^31 bis +2^31
    2^31 = 2 147 483 648

    cu,
    Andreas

    --
    MudGuard? Siehe http://www.Mud-Guard.de/
    Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hallo Andreas,

      Dir ist bekannt, daß numerische Datentypen nur innerhalb gewisser Grenzen funktionieren?

      Und für solche Fälle gibt es http://de3.php.net/bc. :)

      Viele Grüße,
      Christian

    2. Hello,

      Dir ist bekannt, daß numerische Datentypen nur innerhalb gewisser Grenzen funktionieren?
      Bei integer meist zwischen -2^31 bis +2^31
      2^31 = 2 147 483 648

      Du kannst den Dividenden aber ruhig als Double anlegen. Es funktioniert trotzdem nicht. Da scheint ein echtes Problem drinzustecken.

      Liebe Grüße aus http://www.braunschweig.de

      Tom

      --
      [ Computer-Camp für PHP-Anwender in den Sommerferien. Programmieren,
        Sport, Fun, Fete. Teilnehmermindestalter Gruppe 1: 14 Jahre
        Mindestalter Gruppe 2+3 18 Jahre, Info bei mir ]
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      1. Hi,

        Du kannst den Dividenden aber ruhig als Double anlegen. Es funktioniert trotzdem nicht.

        http://www.php.net/manual/de/language.operators.arithmetic.php#42066

        Wobei ich das "unpredictable" reletaviert sehen möchte. Wenn ich gerade keinen Denkfehler mache, ist "a % b" in PHP identisch mit "a % 2147483648 % b".

        Cheatah

        --
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
      2. Hallo Tom,

        Du kannst den Dividenden aber ruhig als Double anlegen. Es funktioniert trotzdem nicht.

        Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_ und daher die Double-Zahl vorher in einen Integer verwandelt wird, bevor Modulo angewendet wird.

        Da scheint ein echtes Problem drinzustecken.

        Double speichert zwar sehr große Zahlen, allerdings nicht mit beliebiger Präzision. 100000000000000000000000000 ist in Double noch darstellbar, ist aber von 100000000000000000000000001 nicht unterscheidbar.

        Viele Grüße,
        Christian

        1. Hallo zusammen,

          Du kannst den Dividenden aber ruhig als Double anlegen. Es funktioniert trotzdem nicht.

          Und wenn man beide nach Double ändert? Immerhin lauten die entsprechenden Funktionen in den meisten Sprachen ähnlich Cs "double fmod(double x, double y)" (In math.h)
          (Die früheste Implementaton, die ich auf die Schnelle gefunden habe ist von SUN von 1993. Würde mich aber arg wundern, wenn es nicht schon 1983 eine gegeben hätte)

          Ist auch im POSIX Standard:
          http://www.opengroup.org/onlinepubs/009695399/functions/fmod.html

          Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_

          Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?

          und daher die Double-Zahl vorher in einen Integer verwandelt wird, bevor Modulo angewendet wird.

          Es ist schon ein klein wenig komplizierter, aber prinzipiell hast Du durchaus Recht. Aber was hat das damit zu tun, das es in PHP nicht klappt?
          Nein, das ist, wenn schon kein direkter Bug, so doch zumindest eine recht merkwürdige Auffassung von Arithmetik.

          Da scheint ein echtes Problem drinzustecken.

          Double speichert zwar sehr große Zahlen, allerdings nicht mit beliebiger Präzision. 100000000000000000000000000 ist in Double noch darstellbar, ist aber von 100000000000000000000000001 nicht unterscheidbar.

          Also die Werte von double hättest Du durchaus aber mal nachrechnen lassen können! ;-)

          so short

          Christoph Zurnieden

          1. Hi,

            Und wenn man beide nach Double ändert?

            siehe mein Posting etwas tiefer.

            Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_
            Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?

            Double ist ein Float-Typus, d.h. er hat eine Beschränkung in der Präzision. Je größer die Werte werden, umso weniger feingranular sind sie. Bei der Modulo-Rechnung kommt es aber eben auf die Körnigkeit an; es ist sozusagen vom Planck'schen Wirkungsquantum des Integers abhängig.

            Aber was hat das damit zu tun, das es in PHP nicht klappt?

            Ich würde sagen, das ist ein Mangel im PHP-Prozessor. Man hätte es nicht so zu implementieren brauchen.

            Cheatah

            --
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. Hi,

              gepostet um "8:50"? Kein Brückentag? Arme Sau!
              Aber ich ja auch nicht.

              Und wenn man beide nach Double ändert?

              siehe mein Posting etwas tiefer.

              Da habe ich zwar nichts gefunden, nehme aber mal an, das das "klappt auch nicht" bedeutet.

              Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_
              Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?

              Double ist ein Float-Typus, d.h. er hat eine Beschränkung in der Präzision. Je größer die Werte werden, umso weniger feingranular sind sie. Bei der Modulo-Rechnung kommt es aber eben auf die Körnigkeit an; es ist sozusagen vom Planck'schen Wirkungsquantum des Integers abhängig.

              Ein einfaches "is'n Bug in PHP" hätt' aber auch schon gereicht, Herr Kollege. ;-)

              so short

              Christoph Zurnieden

              1. Hi,

                gepostet um "8:50"? Kein Brückentag? Arme Sau!

                och, wenn die halbe Firma nicht da ist, kann man wenigstens mal effizient etwas konzipieren ...

                Aber ich ja auch nicht.

                Willkommen im Club :-)

                Und wenn man beide nach Double ändert?
                siehe mein Posting etwas tiefer.
                Da habe ich zwar nichts gefunden,

                [pref:t=82037&m=477512] besteht im Wesentlichen aus einem weiteren Link.

                nehme aber mal an, das das "klappt auch nicht" bedeutet.

                Jupp.

                Ein einfaches "is'n Bug in PHP" hätt' aber auch schon gereicht, Herr Kollege. ;-)

                Beschränkung ist wohl der passende Ausdruck. Oder wenigstens Broken As Designed (abgekürzt "BAD") :-)

                Cheatah

                --
                X-Will-Answer-Email: No
                X-Please-Search-Archive-First: Absolutely Yes
          2. Hallo,

            Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_
            Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?

            Nichts. Es sind rein mathematische Gründe. Das Ergebnis der modulo-Operation ist der _ganzzahlige_ Rest der Division zweier _ganzer_ Zahlen. Modulo ist also definiert als:

            x mod y = z; mit: x Element von Z, y Element von Z, z Element von Z
            wobei Z = Menge der ganzen Zahlen = N und negative von N.

            Beispiele:

            123 mod 2 = 1
            124 mod 3 = 1
            1239 mod 29 = 21

            aber:
            123.9 mod 2.9 = 2.1 (nicht definiert).

            viele Grüße

            Axel

            1. Hello,

              [...]
              einen größeren ganzzahligen Typ als Integer kennt PHP aber nicht, oder?

              Liebe Grüße aus http://www.braunschweig.de

              Tom

              --
              [ Computer-Camp für PHP-Anwender in den Sommerferien. Programmieren,
                Sport, Fun, Fete. Teilnehmermindestalter Gruppe 1: 14 Jahre
                Mindestalter Gruppe 2+3 18 Jahre, Info bei mir ]
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              1. Hi,

                einen größeren ganzzahligen Typ als Integer kennt PHP aber nicht, oder?

                [pref:t=82037&m=477502]

                cu,
                Andreas

                --
                MudGuard? Siehe http://www.Mud-Guard.de/
                Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
                1. Hello,

                  einen größeren ganzzahligen Typ als Integer kennt PHP aber nicht, oder?

                  [pref:t=82037&m=477502]

                  Das ist ja fein, aber es muss bei der Installation mit eingerichtet worden sein. Und das ist meistens leider nicht der Fall.

                  Kann man das einfach "nachinstallieren"? (LAMP)

                  Liebe Grüße aus http://www.braunschweig.de

                  Tom

                  --
                  [ Computer-Camp für PHP-Anwender in den Sommerferien. Programmieren,
                    Sport, Fun, Fete. Teilnehmermindestalter Gruppe 1: 14 Jahre
                    Mindestalter Gruppe 2+3 18 Jahre, Info bei mir ]
                  Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                  1. Hi,

                    einen größeren ganzzahligen Typ als Integer kennt PHP aber nicht, oder?
                    [pref:t=82037&m=477502]
                    Das ist ja fein, aber es muss bei der Installation mit eingerichtet worden sein. Und das ist meistens leider nicht der Fall.

                    Zitat aus der dort verlinkten Seite:

                    Seit PHP 4.0.4 ist libbcmath in PHP enthalten. Sie brauchen keine externen Bibliotheken für diese Erweiterung.

                    cu,
                    Andreas

                    --
                    MudGuard? Siehe http://www.Mud-Guard.de/
                    Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
                    1. Hello,

                      Hi,

                      einen größeren ganzzahligen Typ als Integer kennt PHP aber nicht, oder?
                      [pref:t=82037&m=477502]
                      Das ist ja fein, aber es muss bei der Installation mit eingerichtet worden sein. Und das ist meistens leider nicht der Fall.

                      Zitat aus der dort verlinkten Seite:

                      Seit PHP 4.0.4 ist libbcmath in PHP enthalten. Sie brauchen keine externen Bibliotheken für diese Erweiterung.

                      Bitte nicht verkürzen:

                      In PHP 4 sind diese Funktionen nur verfügbar, wenn PHP mit --enable-bcmath konfiguriert wurde. [...]

                      Leider habe ich das nirgends getan.
                      Deshalb war meine Frage: kann ich das nachholen ohne PHP vollständig neu zu kompilieren. Das ist nämlich etwas stressig wegen GD-Lib und Freetype...

                      Liebe Grüße aus http://www.braunschweig.de

                      Tom

                      --
                      [ Computer-Camp für PHP-Anwender in den Sommerferien. Programmieren,
                        Sport, Fun, Fete. Teilnehmermindestalter Gruppe 1: 14 Jahre
                        Mindestalter Gruppe 2+3 18 Jahre, Info bei mir ]
                      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            2. Hi,

              Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_
              Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?
              Nichts. Es sind rein mathematische Gründe.

              Die Modulis (Modulus ist doch o-Deklination, oder?) aus der Mathematik und der Informatik werden unterschiedlich benutzt.
              Während es in der Mathematik eher um Kongruenz geht, geht's in der Informatik meist schlicht um den Rest.

              123 mod 2 = 1
              124 mod 3 = 1
              1239 mod 29 = 21

              aber:
              123.9 mod 2.9 = 2.1 (nicht definiert).

              Hier kommt allerdings der Fakt in's Spiel, das bei den meisten Rechner-Architekturen nur Brüche benutzt werden können. (12/1, 1/3,2/77 aber z.B. nicht Pi, sqrt(2) o.ä.)
              Brüche können jedoch mühelos erweitert werden.

              123.9 mod 2.9 = 2.1

              123,9 : 2,9 = q + 2,1
              <=> (1239 : 29)/10 = (q + 21)/10

              (1239 mod 29)/10 = 21/10

              Deshalb kann es fmod(3) geben.
              (Alles natürlich stark verkürzt. Bei Unklarheiten ruhig nachfragen)

              so short

              Christoph Zurnieden

              1. Hallo,

                Der Begriff Modulo wird in der Mathematik und der Informatik unterschiedlich benutzt.
                Während es in der Mathematik eher um Kongruenz geht,

                Nein. Auch die Mathematik beschäftigt sich mit Problemen der Ganzzahldivision. Stichwort: Restklassenring.

                geht's in der Informatik meist schlicht um den Rest.
                Hier kommt allerdings der Fakt in's Spiel, das bei den meisten Rechner-Architekturen nur Brüche benutzt werden können. (12/1, 1/3,2/77 aber z.B. nicht Pi, sqrt(2) o.ä.)
                Brüche können jedoch mühelos erweitert werden.
                Deshalb kann es fmod(3) geben.
                (Alles natürlich stark verkürzt. Bei Unklarheiten ruhig nachfragen)

                Definiere "Rest" im Kontext von gebrochenen Zahlen!
                Du behauptest:
                123.9 mod 2.9 = 2.1, weil ((123.9*10) mod (2.9*10))/10 = 21/10

                Ich behaupte:
                123.9 / 2.9 ergibt 42, Rest 2.1
                42 * 2.9 = 121,8; 121,8 + 2.1 = 123,9

                aber auch:
                123.9 / 2.9 ergibt 42.7, Rest 0.07
                42.7 * 2.9 = 123,83; 123,83 + 0.07 = 123,9

                und auch:
                123.9 / 2.9 ergibt 42.72, Rest 0.012
                42.72 * 2.9 = 123,888; 123,888 + 0.012 = 123,9

                und sogar:
                123.9 / 2.9 ergibt 42.6, Rest 0.36
                42.6 * 2.9 = 123,54; 123,54 + 0.36 = 123.9

                und
                123.9 / 2.9 ergibt 42.1, Rest 1.81
                42.1 * 2.9 = 122,09; 122,09 + 1.81 = 123.9

                Im Kontext der gebrochenen Zahlen hat
                123.9 mod 2.9 also beliebig viele Lösungen.

                viele Grüße

                Axel

                1. Hi,

                  Im Kontext der gebrochenen Zahlen hat
                  123.9 mod 2.9 also beliebig viele Lösungen.

                  nicht wenn a mod b := a - (a div b)*b.

                  Cheatah

                  --
                  X-Will-Answer-Email: No
                  X-Please-Search-Archive-First: Absolutely Yes
                  1. Hallo,

                    Im Kontext der gebrochenen Zahlen hat
                    123.9 mod 2.9 also beliebig viele Lösungen.
                    nicht wenn a mod b := a - (a div b)*b.

                    Dann definiere div im Kontext gebrochener Zahlen ;-)). Das bedeutet: "Was versteht man unter dem _ganzahligen_ Quotienten zweier Brüche?". Bei:

                    123.9 mod 2.9 = 123.9 - (123.9 div 2.9) * 2.9
                                  = 123.9 - 42 * 2.9
                                  = 123.9 - 121.8
                                  = 2.1

                    scheint das noch logisch. Aber wenn gilt:
                    123.9 div 2.9 = 42, was ist dann
                    100 div (10/3) oder
                    (100/3) div 2 ...?

                    viele Grüße

                    Axel

                    1. Hallo,

                      Dann definiere div im Kontext gebrochener Zahlen ;-)). Das bedeutet: "Was versteht man unter dem _ganzahligen_ Quotienten zweier Brüche?".

                      Vergiss es ;-)). Da jeder Bruch durch Erweiterung gleichnamig zu einem anderen Bruch gemacht werden kann und da gilt:

                      (x/n) div (y/n) = x div y, weil (x/n)/(y/n) = (x/n)*(n/y) = x/y

                      kann jede div-Operation mit Brüchen in eine div-Operation zweier ganzer Zahlen überführt werden. Damit ist auch:

                      (a/n) mod (b/n) = (a/n) - ((a/n) div (b/n)) * b/n
                                      = (a/n) - (a div b) * b/n
                                      = ((a - (a div b) * b)) / n
                      mit
                      a mod b         = a - (a div b) * b
                      ist
                      (a/n) mod (b/n) = (a mod b) / n

                      viele Grüße

                      Axel

                      1. Hallo,

                        Dann definiere div im Kontext gebrochener Zahlen ;-)). Das bedeutet: "Was versteht man unter dem _ganzahligen_ Quotienten zweier Brüche?".
                        Vergiss es ;-)). Da jeder Bruch durch Erweiterung gleichnamig zu einem anderen Bruch gemacht werden kann und da gilt:
                        (x/n) div (y/n) = x div y, weil (x/n)/(y/n) = (x/n)*(n/y) = x/y

                        kann jede div-Operation mit Brüchen in eine div-Operation zweier ganzer Zahlen überführt werden. Damit ist auch:

                        Da sich keiner beschwert hat, dürfte es eingegangen sein.
                        In der einen oder anderen Bedeutung von "eingegangen" ;-)

                        Danke für die fundierte Unterstützung, aber ich möchte noch darauf hinweisen, das das nur für Reelle Zahlen gilt, bei transzendenten Zahlen hingegen könntest Du durchaus in Teufels Küche und dorten schwer in's Schwitzen kommen ;-)

                        so short

                        Christoph Zurnieden

                        1. Hallo,

                          Danke für die fundierte Unterstützung, aber ich möchte noch darauf hinweisen, das das nur für Reelle Zahlen gilt, bei transzendenten Zahlen hingegen könntest Du durchaus in Teufels Küche und dorten schwer in's Schwitzen kommen ;-)

                          Ich sprach auch nur von Brüchen, zusätzlich zu den ganzen Zahlen, also von rationalen Zahlen. Das Schwitzen finge, meiner Meinung nach, auch bei anderen irrationalen Zahlen als transzendenten schon an. Man muss also gar nicht erst die transzendenten Zahlen bemühen. Somit gilt das nur für rationale Zahlen, z.B. nicht für Wurzel aus 2.

                          viele Grüße

                          Axel

          3. Hallo Christoph,

            Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_

            Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?

            Modulo ist als ganzzahliger Rest definiert. Natürlich kann man auch den Rest einer Division mit gebrochenen Zahlen berechnen, dies ist dann aber nicht mehr Modulo. IMHO sind die Funktionen fmod* unglücklich benannet; fremainder oder so wäre besser gewesen.

            Double speichert zwar sehr große Zahlen, allerdings nicht mit beliebiger Präzision. 100000000000000000000000000 ist in Double noch darstellbar, ist aber von 100000000000000000000000001 nicht unterscheidbar.

            Also die Werte von double hättest Du durchaus aber mal nachrechnen lassen können! ;-)

            Ich steh gerade auf dem Schlauch?

            Viele Grüße,
            Christian

            1. Hi,

              Weil beim Double aus naheliegenden Gründen der Modulo-Operator nicht implementiert sein _kann_

              Solche Gründe liegen mir fern, sprich: was ist in PHP so speziell, das es nicht funktionieren _kann_?

              Modulo ist als ganzzahliger Rest definiert. Natürlich kann man auch den Rest einer Division mit gebrochenen Zahlen berechnen, dies ist dann aber nicht mehr Modulo. IMHO sind die Funktionen fmod* unglücklich benannet; fremainder oder so wäre besser gewesen.

              Ja, deshalb gibt's das auch noch dazu: remainder(3) ;-)
              (Ist aber relativ neu und noch nicht überall eingebaut)

              Double speichert zwar sehr große Zahlen, allerdings nicht mit beliebiger Präzision. 100000000000000000000000000 ist in Double noch darstellbar, ist aber von 100000000000000000000000001 nicht unterscheidbar.

              Also die Werte von double hättest Du durchaus aber mal nachrechnen lassen können! ;-)

              Ich steh gerade auf dem Schlauch?

              Ich weiß zwar, was Du meinst, nur ist das Beispiel recht unglücklich gewählt und noch unglücklicher formuliert.

              Auf dem x86-32 ist das double normalerweise 2^64 Bit groß. (Übrigens deutlich weniger, als Dein 10^26 ;-). 2^64 ist von 2^64+1 durchaus zu unterscheiden, allerdings ist der eigentliche Wert nicht mehr nachvollziehbar, nur noch die Ungleichheit.
              Es gibt natürlich auch Implementationsfehler. So ist hier 1/((2^64)) das gleiche wie 1/((2^64)+1), wer den Fehler produziert weiß ich nicht. (Kann auch ein off-by-one irgendwo sein, da 1/((2^64)+2) klappt) Daneben gibt es auch noch Rundungs- und Umbaufehler und was weiß ich noch alles. Bei großen Zahlen ist es besser stets nur mit Integern zu arbeiten. Für die meisten Sprachen gibt es "Bignum" Bibliotheken - oder wie sie auch heißen mögen - die derartiges zur Verfügung stellen.

              so short

              Christoph Zurnieden