2012-03-08 24 views
9

Mam dziwne zachowanie, zastanawiałem się, czy ktoś może mi coś wyjaśnić.Negacja Hexa w PHP, zabawne zachowanie

Sprawdź to

$hex = 0x80008000; 

print_r(decbin(intval($hex)) . '<br/>'); 
print_r(decbin($hex)); 

Wyjścia

10000000000000001000000000000000 
10000000000000001000000000000000 

jak oczekiwano.

Ale

$hex = 0x80008000; 

print_r(decbin(~intval($hex)) . '<br/>'); 
print_r(decbin(~$hex)); 

Wyjścia

1111111111111110111111111111111 
1111111111111111111111111111111 

Dlaczego środkowy bit nie przełączania kiedy $hex jest negowany?

+0

Jakiej wersji PHP używasz? Drugi przypadek działa dla mnie na 5.3.6 –

+0

Używam 5.3.8 i problem istnieje. – Pateman

+0

Używam 5.2.17 – Vigrond

Odpowiedz

0

Podam tutaj moje własne pytanie.

Tak, jest to różnica 32-bitowa/64-bitowa.

W systemach 32-bitowych typ float musi zająć dwa obszary pamięci, aby uzyskać wymagane 64 bity. Php używa podwójnej precyzji (zobacz: http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers)

Wartość $ hex jest równa liczbie zmiennoprzecinkowej. Funkcje Intval i Decbin przekształcają to w typ int (pierwszy przykład powyżej)

W drugim przykładzie używamy operatora bitowego BEFORE, zanim użyjemy decbin. To odwraca najpierw bity w podwójnej precyzji, a następnie jest zamieniane na sekundę.Dając nam coś innego, niż się spodziewaliśmy.

Rzeczywiście, jeśli stawiamy negować wewnątrz intval() tak:

$hex = 0x80008000; 

print_r(decbin(intval(~$hex)) . '<br/>'); 
print_r(decbin(~$hex)); 

Dostajemy

1111111111111111111111111111111 
1111111111111111111111111111111 

jako wyjście.

Nie jestem wystarczająco dobry, aby udowodnić to z matematyki (które można znaleźć za pomocą tego artykułu http://en.wikipedia.org/wiki/Double_precision). Ale może, gdy będę miał czas później -_-

Myślę, że bardzo ważne jest, aby dowiedzieć się, w jaki sposób liczby są reprezentowane w komputerach, abyśmy mogli zrozumieć anomalie takie jak to i nie nazywać ich błędami.

-1

Prawdopodobnie sprawa objętych tym:

Od strony operatorów php bitowe http://us3.php.net/manual/en/language.operators.bitwise.php

NOT lub uzupełniają operator (~) i ujemnych liczb binarnych może być mylące.

~ 2 = -3 ponieważ użyć formuły ~ x = -x - 1 bitowe dopełnienie liczby dziesiętnej jest negacja liczby minus 1.

UWAGA: tylko za pomocą 4 bitów tutaj przykłady poniżej, ale w rzeczywistości PHP używa 32 bitów.

Konwersja dodatnią liczbę dziesiętną (tj -3) w binarnym trwa 3 etapy: 1) przekształcają pozytywną wersję liczbą dziesiętną w binarne (to znaczy: 3 = 0011), 2) odwraca bitów (tj 0011 staje się 1100) 3) dodaj 1 (tj.: 1100 + 0001 = 1101)

Być może zastanawiasz się, w jaki sposób 1101 = -3. Cóż PHP używa metody "02's uzupełnienie" do renderowania negatywnych liczb binarnych. Jeśli lewy najbardziej bit jest 1, to liczba binarna jest ujemna i odwracasz bity i dodajesz 1. Jeśli jest 0, to jest dodatnie i nie musisz robić niczego. Więc 0010 byłby pozytywny 2. Jeśli jest 1101, to jest ujemny i odwracasz bity, aby uzyskać 0010. Dodaj 1, a otrzymasz 0011, co równa się -3.

+0

Nie sądzę, że jest to związane z pytaniem. Z mojego rozumowania 'intval ($ hex)' powinno być dokładnie równoważne '$ hex', więc spodziewam się' ~ intval ($ hex) === ~ $ hex'. –

+0

Tak, nie konwertuję niczego tutaj, po prostu reprezentuję liczby w formacie binarnym. – Vigrond