z pływakiem, twój założenie $x == $x + 1
niekoniecznie jest prawdą:
$x=2;
echo ((float)($x+1)==(float)($x))?'EQUAL':'Not Equal';
daje "nie równa się".
W konwerterze połączonym w komentarzach (http://www.h-schmidt.net/FloatConverter/IEEE754.html) można go odtworzyć. dziesiętny 2.0
daje 0x40000000
, dziesiętny 3.0
daje 0x40400000
, więc są one rzeczywiście różne, jeśli chodzi o reprezentację float IEEE754.
Podczas gdy np. Dziesiętny 0.1
nie może być reprezentowany jako zmienny: 0x3dcccccd
, który jest 0.10000000149011612
.
Jaki jest dziesiętny 9223372036854775807
? To jest 0x5f000000
, która jest 9.223372E18
, która jest 9223372180000000000
.
Jaki jest dziesiętny 9223372036854775808
(PHP_MAX_INT + 1
)? To także 0x5f000000
.
Co to jest dziesiętna 9223372036854776832
(PHP_MAX_INT + 1025
)? To także 0x5f000000
.
Jaki jest dziesiętny 9223372036854776833
(PHP_MAX_INT + 1026
)? To także 0x5f000000
.
Wszystkie są takie same.
Natomiast np .: dziesiętnie 9223373000000000000
(PHP_MAX_INT + 963145224193
)? To jest 0x5f000001
, czyli 9.223373E18
, czyli 9223373000000000000
.
Teraz, dlaczego:
((float)($x+1025)==(float)($x+1026))?'EQUAL':'Not Equal';
plon "nie równa się"?
Dodajesz liczbę całkowitą do 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);
plony:
int(9223372036854775807)
int(9223372036854775806)
float(9.2233720368548E+18)
PHP niejawnie konwertuje liczby całkowite zbyt duże, aby pływaka. I w tym przypadku zagubiłeś się w wewnętrznych aplikacjach PHP (przynajmniej moim zdaniem), ponieważ od tego momentu nigdy się nie dowiesz, co się stanie (nie znając wewnętrznych elementów PHP, nie krępuj się jednak poprawić).
odnotować to:
$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);
Wydajność:
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)
Po dodaniu całkowitą ($x+1026
) do PHP_MAX_INT
przekształcany jest do pływaka, a po dodaniu do pływaka ($x+1026.0
) Oczywiście jest to również float. Ale, oczywiście, nie są one takie same wewnętrznie, patrz porównania powyżej.
Konkluzja:
- Nie porównuj pływaków na rzecz równości
- Bądź ostrożny o swoich odlewów;
(float)($x+1026)
jest dodawaniem całkowitym, a następnie odlewane do postaci pływającej, natomiast (float)($x+1026.0)
przekształca $x
w zmienną, następnie dodaje zmienną 1026.0
, a następnie rzuca (zbytecznie), aby unosić się w powietrzu.
Edit: dodatkowo, patrz:
Trzeba zacząć patrząc na [poziomie nieco reprezentacji pływaków] (https: // en. wikipedia.org/wiki/Floating_point) i to będzie się różnić w zależności od tego, czy używasz 32-bitowej, czy 64-bitowej wersji PHP –
, którą wersję PHP posiadasz? z moim testem mam "nie równy" z "$ x + 10" na przykład – mmm
Spójrz na [ten konwerter] (http://www.h-schmidt.net/FloatConverter/IEEE754.html), który pozwala aby zobaczyć reprezentację zmiennoprzecinkową dla różnych numerów –