2012-03-08 4 views
9

Получил какое-то странное поведение. Мне было интересно, может ли кто-нибудь прояснить меня.Отрицание Hex в PHP, смешное поведение

Проверьте это

$hex = 0x80008000; 

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

Выходы

10000000000000001000000000000000 
10000000000000001000000000000000 

Как и следовало ожидать.

Но

$hex = 0x80008000; 

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

Выходы

1111111111111110111111111111111 
1111111111111111111111111111111 

Почему средний бит не переключение, когда $hex отрицается?

+0

Какую версию PHP вы используете? Второй случай работает для меня в 5.3.6 –

+0

Я запускаю 5.3.8, и проблема существует. – Pateman

+0

Я использую 5.2.17 – Vigrond

ответ

0

Собираюсь сделать снимок на свой вопрос здесь.

Да, это 32-разрядная/64-разрядная разница.

В 32-разрядных системах тип float должен занимать два пространства памяти, чтобы получить требуемые 64 бита. Php использует двойную точность (см. http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers)

$ hex оценивает тип float. Функции Intval и decbin преобразуют это в тип int (первый пример выше)

Во втором примере мы используем не побитовый оператор, прежде чем будем использовать decbin. Это сначала сбрасывает биты в области памяти с двойной памятью с двойной точностью, а затем преобразуется в int second.Дарить нам нечто иное, чем мы ожидали.

В самом деле, если мы помещаем нивелируют внутри intval() следующим образом:

$hex = 0x80008000; 

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

Мы получаем

1111111111111111111111111111111 
1111111111111111111111111111111 

выходе.

Я недостаточно хорош, чтобы доказать это с математикой еще (что может быть выяснено с помощью этой статьи http://en.wikipedia.org/wiki/Double_precision). Но может быть, когда у меня будет время позже. -_-

Я думаю, что очень важно узнать, как цифры представлены в компьютерах, чтобы мы могли понять аномалии, подобные этому, и не называть их ошибками.

-1

Возможно, дело подпадает под это:

На странице операторов PHP битовые http://us3.php.net/manual/en/language.operators.bitwise.php

функция НЕ или дополнить оператор (~) и отрицательные двоичные числа могут вводить в заблуждение.

~ 2 = -3, потому что вы используете формулу ~ х = х - 1 Поразрядный дополнение десятичного числа является отрицанием числа минус 1.

Примечание: только с помощью 4-х битов здесь примеры ниже, но на самом деле PHP использует 32 бита.

Преобразование отрицательного десятичного числа (то есть: -3) в бинарный код занимает 3 шагов: 1) преобразуют положительную версию десятичного числа в двоичном (то есть: 3 = 0011) 2) переворачиваются биты (то есть: 0011 становится 1100) 3) добавить 1 (то есть: 1100 + 0001 = 1101)

Возможно, вам интересно, как 1101 = -3. Ну, PHP использует метод «дополнение 2» для рендеринга отрицательных двоичных чисел. Если самый старший бит равен 1, тогда двоичное число отрицательно, и вы переворачиваете биты и добавляете 1. Если это 0, то это положительно, и вам не нужно делать что угодно. Таким образом, 0010 будет положительным 2. Если это 1101, это отрицательно , и вы переворачиваете биты, чтобы получить 0010. Добавьте 1, и вы получите 0011, который равен -3.

+0

Я не думаю, что это связано с вопросом. По моему мнению, 'intval ($ hex)' должен быть точно эквивалентен '$ hex', поэтому я бы ожидал' ~ intval ($ hex) === ~ $ hex'. –

+0

Да, я ничего не конвертирую здесь, просто представляя числа в двоичном формате. – Vigrond