С поплавком, ваше предположение $x == $x + 1
не всегда верно:
$x=2;
echo ((float)($x+1)==(float)($x))?'EQUAL':'Not Equal';
дает "не равно".
В конвертере, указанном в комментариях (http://www.h-schmidt.net/FloatConverter/IEEE754.html), вы можете воспроизвести это. десятичный 2.0
дает 0x40000000
, десятичный 3.0
дает 0x40400000
, поэтому они действительно различаются, когда речь идет о представлении float IEEE754.
Принимая во внимание, что, например, десятичный 0.1
не может быть представлен как поплавок: 0x3dcccccd
, что составляет 0.10000000149011612
.
Что такое десятичный 9223372036854775807
? Это 0x5f000000
, что составляет 9.223372E18
, что составляет 9223372180000000000
.
Что такое десятичный 9223372036854775808
(PHP_MAX_INT + 1
)? Это тоже 0x5f000000
.
Что такое десятичный 9223372036854776832
(PHP_MAX_INT + 1025
)? Это тоже 0x5f000000
.
Что такое десятичный 9223372036854776833
(PHP_MAX_INT + 1026
)? Это тоже 0x5f000000
.
Все они одинаковые.
Принимая во внимание, что, например: десятичный 9223373000000000000
(PHP_MAX_INT + 963145224193
)? Это 0x5f000001
, что составляет 9.223373E18
, что составляет 9223373000000000000
.
Теперь, почему:
((float)($x+1025)==(float)($x+1026))?'EQUAL':'Not Equal';
выход "не равно"?
Вы добавляете целое число в PHP_MAX_INT
.
$x=PHP_INT_MAX;
$y=PHP_INT_MAX-1;
$z=PHP_INT_MAX+1;
var_dump($x);
var_dump($y);
var_dump($z);
выходы:
int(9223372036854775807)
int(9223372036854775806)
float(9.2233720368548E+18)
PHP неявно преобразует целые числа слишком большие, чтобы плавать. И вот где вы в основном потеряны в PHP-внутренностях (по крайней мере, на мой взгляд), потому что отсюда вы никогда не узнаете, что произойдет (не зная PHP-внутренности, не стесняйтесь меня исправлять).
Обратите внимание это:
$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);
выходы:
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)
Если добавить целое число ($x+1026
) для PHP_MAX_INT
, он преобразуется в поплавок, и при добавлении поплавок ($x+1026.0
), он тоже плавает, конечно. Но, очевидно, они не являются внутренними, см. Сравнения выше.
Итог:
- Не сравнивайте поплавки для равенства
- Будьте осторожны о ваших слепков;
(float)($x+1026)
представляет собой целочисленное добавление и впоследствии литое в float, тогда как (float)($x+1026.0)
преобразует $x
в float, затем добавляет поплавок 1026.0
, а затем бросает (излишне) плавать.
Edit: дополнительно, см:
Вы должны начать смотреть на [представлении битового уровня поплавков] (https: // эн. wikipedia.org/wiki/Floating_point), и это также будет зависеть от того, используете ли вы 32-разрядный или 64-разрядный PHP –
, какую версию PHP у вас есть? с моим тестом я «не равный» с «$ x + 10» для примера – mmm
Взгляните на [этот конвертер] (http://www.h-schmidt.net/FloatConverter/IEEE754.html), который позволяет вам чтобы увидеть представление с плавающей точкой для разных чисел –