5
<?php 
$x=PHP_INT_MAX; 
echo ((float)($x+1026)==(float)($x))?'EQUAL':'Not Equal'; 

Ich weiß Gleitpunktarithmetik exakt ist nicht und und x + 1 sind so nah beieinander $ $ x hinzugefügt wird, dass sie abgerundet sind, auf den gleichen Gleitkommawert und es zeigt die Ausgabe als EQUAL, wenn Sie eine Zahl zwischen 1 und 1025 verwenden, aber erst nachdem Sie einen Wert jenseits von 1025 verwendet haben, wird die Ausgabe als 'Ungleich' ausgegeben. Ich möchte wissen warum? Was ist der Grund dafür? Warum erst nach 1025?Warum zwei float Variablen mit PHP_INT_MAX Werten gleich sind, es sei denn einer von ihnen mit einem Wert von mehr als 1025

+2

Sie suchen beginnen müssen im [Bit-Level-Darstellung von Schwimmern] (https: // en. wikipedia.org/wiki/Floating_point) und dies hängt auch davon ab, ob Sie 32-Bit oder 64-Bit PHP –

+0

welche PHP-Version haben Sie? mit meinem Test habe ich "nicht gleich" mit "$ x + 10" für zB – mmm

+1

Werfen Sie einen Blick auf [diesen Konverter] (http://www.h-schmidt.net/FloatConverter/IEEE754.html), der Ihnen erlaubt um die Float-Darstellung für verschiedene Zahlen zu sehen –

Antwort

4

mit Schwimmer, Ihre Annahme $x == $x + 1 ist nicht unbedingt wahr:

$x=2; 
echo ((float)($x+1)==(float)($x))?'EQUAL':'Not Equal'; 

ergibt "nicht gleich".

In den Konverter in den Kommentaren (http://www.h-schmidt.net/FloatConverter/IEEE754.html) verlinkt, können Sie dies reproduzieren. dezimal 2.0 ergibt 0x40000000, dezimal 3.0 ergibt 0x40400000, so dass sie in der Tat unterscheiden, wenn es um IEEE754 Float-Darstellung kommt.

Während z. B. dezimal 0.1 nicht als Float dargestellt werden kann: 0x3dcccccd, die 0.10000000149011612 ist.

Was ist Dezimal 9223372036854775807? Das ist 0x5f000000, das ist 9.223372E18, das 9223372180000000000 ist.

Was ist die Dezimalzahl 9223372036854775808 (PHP_MAX_INT + 1)? Das ist 0x5f000000, auch.

Was ist die Dezimalzahl 9223372036854776832 (PHP_MAX_INT + 1025)? Das ist 0x5f000000, auch.

Was ist Dezimal 9223372036854776833 (PHP_MAX_INT + 1026)? Das ist 0x5f000000, auch.

Sie sind alle gleich.

Während z. B. dezimal 9223373000000000000 (PHP_MAX_INT + 963145224193)? Das ist 0x5f000001, das ist 9.223373E18, das ist 9223373000000000000. Jetzt

, warum tut:

((float)($x+1025)==(float)($x+1026))?'EQUAL':'Not Equal'; 

yield "Nicht gleich"?

Sie fügen eine Ganzzahl zu PHP_MAX_INT hinzu.

$x=PHP_INT_MAX; 
$y=PHP_INT_MAX-1; 
$z=PHP_INT_MAX+1; 
var_dump($x); 
var_dump($y); 
var_dump($z); 

ergibt:

int(9223372036854775807) 
int(9223372036854775806) 
float(9.2233720368548E+18) 

PHP implizit ganzen Zahlen zu groß zu schweben umwandelt. Und das ist, wo Sie im Grunde genommen in PHP-Interna verloren sind (zumindest meiner Meinung nach), weil Sie von hier aus nie wissen werden, was passieren wird (ohne PHP-Interna zu kennen, fühlen Sie sich frei, mich zu korrigieren).

Hinweis dies:

$x=PHP_INT_MAX; 
$a=(float)($x+1025.0); // 1025 float 
$b=(float)($x+1026.0); // 1026 float 
$c=(float)($x+1025); // 1025 int 
$d=(float)($x+1026); // 1026 int 
var_dump($x); 
var_dump($a); 
var_dump($b); 
var_dump($c); 
var_dump($d); 
var_dump($a==$b); 
var_dump($a===$b); 
var_dump($c==$d); 
var_dump($c===$d); 

ergibt:

int(9223372036854775807) 
float(9.2233720368548E+18) 
float(9.2233720368548E+18) 
float(9.2233720368548E+18) 
float(9.2233720368548E+18) 
bool(true) 
bool(true) 
bool(false) 
bool(false) 

Wenn Sie eine ganze Zahl ($x+1026) zu PHP_MAX_INT hinzufügen, wird sie umgewandelt zu schweben, und wenn man einen Schwimmer hinzufügen ($x+1026.0), es ist natürlich auch float. Aber offensichtlich sind sie intern nicht identisch, siehe die obigen Vergleiche.

Fazit:

  • nicht schwimmt auf Gleichheit vergleichen
  • über Ihre Abgüsse Vorsicht; (float)($x+1026) ist eine Ganzzahladdition und wird anschließend in float umgewandelt, während (float)($x+1026.0)$x in float konvertiert, dann den float 1026.0 hinzufügt und dann (überflüssig) in float umwandelt.

Edit: zusätzlich finden Sie unter: