Побитовые операции над большими целыми числами в PHP 5.2 и PHP 5.3


Я опущу подробности того, как я пришел к этому, но дело в том, что приведенный ниже код дает разные результаты на PHP 5.2 x86 и PHP 5.3 x86.

<?php

$result = (((-1035721791 + -2004767255) ^ 3402727701) + 4148612726) ^ -759268493;
echo 'Platform: ' . php_uname(), PHP_EOL;
echo 'PHP version: ' . PHP_VERSION, PHP_EOL;
echo 'Max integer: ' . PHP_INT_MAX, PHP_EOL;
echo 'Result: ' . $result, PHP_EOL;

Результаты таковы:

Linux x64, PHP 5.3

Platform: Linux Test1 3.2.0-25-generic #40-Ubuntu SMP Wed May 23 20:30:51 UTC 2012 x86_64
PHP version: 5.3.10-1ubuntu3.2
Max integer: 9223372036854775807
Result: -1511693242

Linux x86, PHP 5.3

Platform: Linux Test2 2.6.32-5-686 #1 SMP Sun May 6 04:01:19 UTC 2012 i686
PHP version: 5.3.3-7+squeeze9
Max integer: 2147483647
Result: -1511693242

Windows x86, PHP 5.3

Platform: Windows NT Test3 6.1 build 7600 i586
PHP version: 5.3.6
Max integer: 2147483647
Result: -1511693242

Linux x86, PHP 5.2

Platform: Linux Test4 2.6.18-8.el5 #1 SMP Thu Mar 15 19:57:35 EDT 2007 i686
PHP version: 5.2.10
Max integer: 2147483647
Result: -1868155656

Последний результат отличается от остальных по какой-то неизвестной мне причине.

Как вы можете видеть, результат выражения -1035721791 + -2004767255 не подходит int32, но PHP 5.3 дает одинаковый результат как на платформах x86, так и на x64. И PHP 5.2 выдает неверный результат на x86.

Задокументирована ли эта разница? Это особенность PHP или ошибка PHP 5.2?

Author: Sergei Morozov, 2012-07-10

1 answers

Когда PHP обнаруживает число, которое не вписывается в PHP_INT_MAX (32 бита на x86), оно преобразует число в число с плавающей точкой:

Если PHP обнаружит число, выходящее за пределы целочисленного типа, оно будет интерпретироваться как число с плавающей точкой. Кроме того, операция , в результате которой число выходит за пределы целочисленного типа, вместо этого вернет значение с плавающей точкой.

Кроме того, Список изменений PHP 5.3 гласит:

Изменена плавающая точка поведение для последовательного использования двойной точности на всех платформах и со всеми компиляторами. (Кристиан Сейлер)

Хотя я не могу подтвердить вам на 100%, что это причина того, что вы видите, я полагаю, что это должно иметь какое-то отношение к этому.

В любом случае, если вы имеете дело с такими большими числами, вам следует перестать полагаться на точность с плавающей точкой и вместо этого использовать расширение, предлагающее поддержку больших чисел, например BC Math или GMP

 4
Author: Lepidosteus, 2012-07-09 21:03:42