PHP-Integer-Überlauf erzwingen

7

Wir haben eine Integer-Arithmetik, die aus historischen Gründen bei PHP genauso funktioniert wie in einigen statisch typisierten Sprachen. Seit dem letzten Upgrade von PHP hat sich das Verhalten für überlaufende Ganzzahlen geändert. Grundsätzlich verwenden wir folgende Formel:

%Vor%

Aber auch mit Konvertierungen:

%Vor%

Ich komme immer noch mit der völlig falschen Nummer ...

Zum Beispiel, mit $ x1 = -1580033017, $ x2 = -2072974554, $ x3 = -1170476976) und $ x4 = -1007518822, endet ich mit -30512150 in PHP und 1617621783 in C #.

Ich addiere einfach $ x1 und $ x2 Ich kann nicht die richtige Antwort bekommen:

In C # bekomme ich

%Vor%

In PHP:

%Vor%

ist das gleiche wie:

%Vor%

Es macht mir nichts aus, eine "IntegerOverflowAdd" Funktion oder etwas zu schreiben, aber ich kann nicht genau herausfinden, wie (-1580033017 + -2072974554) 641959725 entspricht. (Ich erkenne, dass es -2147483648 + (2 * 2 ^ 31), aber -2147483648 + 2 ^ 31 ist -1505523923 was größer ist als Int.Min also warum fügst du 2 * 2 ^ 31 hinzu und nicht 2 ^ 31?)

Jede Hilfe wäre willkommen ...

    
Kris Erickson 19.11.2008, 02:26
quelle

6 Antworten

13

Also habe ich das Problem gelöst und viel über PHP herausgefunden (zumindest in der Art, wie es den Integer-Überlauf behandelt).

1) Es hing vollständig davon ab, auf welcher Plattform die Maschine lief, welche Version von PHP, ob Suhosin Hardened PHP lief oder nicht und wie viele Bits es kompiliert wurde (32 oder 64). 6 Maschinen verhielten sich so, wie ich es erwartet hatte (was eigentlich falsch war, zumindest nach ihrer Dokumentation falsch) und 3 Maschinen verhielten sich auf eine Weise, die ich immer noch nicht erklären konnte, und 3 Maschinen verhielten sich entsprechend dem Befehl intval Dokumentation.

2) Intval soll PHP_MAX_INT zurückgeben, wenn int & gt; PHP_MAX_INT (nicht int & amp; 0xffffffff), aber dies geschieht nur bei einigen Versionen von PHP4 und PHP5. Verschiedene Versionen von PHP geben unterschiedliche Werte zurück, wenn int & gt; PHP_MAX_INT.

3) Der folgende Code kann 3 verschiedene Ergebnisse zurückgeben (siehe 1):

%Vor%

Es kann zurückkehren (was für Intval richtig zu sein scheint, aber für & amp; 0xffffff falsch ist)

%Vor%

Und es kann zurückkehren (was der PHP-Dokumentation für intval widerspricht):

%Vor%

Und auf 64-Bit-Maschinen gibt es zurück (was korrekt ist):

%Vor%

Lösung

Jedenfalls brauchte ich eine Lösung, die auf all diesen Plattformen funktioniert und nicht von Macken einer bestimmten Version von PHP abhängig ist, die mit einem bestimmten Max int kompiliert wurde. So cam ich mit der folgenden Cross-PHP dreißig TwoBitIntval Funktion:

%Vor%

Kommentar

Ich denke, die Entwickler von PHP hätten sagen sollen, dass Int ein 32 Bit Int ist, egal ob es auf einem 32- oder 64- oder 128-Bit-Rechner läuft (wie der DotNet CLR) und nicht zufällig hochkonvertiert wurde Es hängt von der Anzahl der Bits ab, unter denen PHP Compiler ist.

    
Kris Erickson 19.11.2008, 23:53
quelle
11

Wenn Sie eine 100% funktionierende Lösung für 32-Bit-Intval auf 32- und 64-Bit-Plattformen haben wollen, dann empfehle ich Ihnen die folgende Lösung:

%Vor%     
user257425 23.01.2010 14:27
quelle
3

Intern verwendet PHP für die meisten Zahlen einen "Ganzzahl" -Typ. Diese gehen jedoch nur so weit: Wenn Sie eine große Ganzzahl zu einer großen Ganzzahl hinzufügen, wird PHP sehen, dass das Ergebnis zu groß ist, um in eine normale Ganzzahl zu passen, und es einer Gleitkommazahl zuweisen wird. Floating-Point-Zahlen (Floats) selbst gehen jedoch nur so hoch, und es gibt einen Punkt um die sechzehnstellige Marke herum, bei dem PHP die Handlung nur ganz verlieren wird.

Es gibt eine Option zur Verwendung beliebiger Mathematik, die Zahlen beliebiger Größe und Genauigkeit unterstützt, dargestellt als Strings . Sehen Sie mehr hier: Ссылка

    
kylex 19.11.2008 02:39
quelle
2

Ich denke, es kann damit zu tun haben, dass die Integer-Zahl in PHP 32 Bits vorzeichenlos ist, wie in C # standardmäßig 32 Bits.

Sie spielen mit Zahlen am Rand des normalen 31-32-Bit-Bereichs.

Siehe zusätzliche Dokumentation im PHP-Handbuch:

Ссылка

Die Größe einer Ganzzahl ist plattformabhängig, obwohl ein Maximalwert von etwa zwei Milliarden der übliche Wert ist (das sind 32 Bit, die signiert sind). PHP unterstützt keine Ganzzahlen ohne Vorzeichen. Die Ganzzahlgröße kann mit der Konstanten PHP_INT_SIZE und der Maximalwert mit der Konstanten PHP_INT_MAX seit PHP 4.4.0 und PHP 5.0.5 bestimmt werden.

    
Vincent 19.11.2008 02:34
quelle
2

Funktioniert das?

%Vor%

Um zu verallgemeinern, könntest du tun (verzeihe Syntaxfehler, ich habe PHP schon lange nicht mehr berührt):

%Vor%     
Chris Jester-Young 19.11.2008 02:36
quelle
1

Überprüfen Sie Ihre Versionsnummer von PHP - ich glaube, es ist möglich, dass Sie unterschiedliche Ergebnisse mit verschiedenen PHP-Versionen erhalten, die möglicherweise unterschiedliche Ganzzahlen unterstützen. Ich glaube, es gab einen Bug mit langen ganzen Zahlen in einer der PHP 5 Versionen.

In der Version PHP 5.2.0 - die Antwort ist GENAU die gleiche wie in C #

1617621783,

Verwenden Sie die genaue Funktion, die Sie oben haben.

Sie können den phpinfo () Befehl verwenden, um Ihre Versionsnummer einfach zu finden.

%Vor%     
JasonMichael 19.11.2008 03:22
quelle

Tags und Links