Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise operations on big integers in PHP 5.2 and PHP 5.3

I'll omit the details of how I came to this but the point is that the code below produces different results on PHP 5.2 x86 and 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;

The results are:

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

The last result is different from the rest for some unknown for me reason.

As you can see, the result of expression -1035721791 + -2004767255 doesn't fit int32 but PHP 5.3 produces the same result both on x86 and x64 platforms. And PHP 5.2 produces incorrect result on x86.

Is this difference documented? Is it a feature of PHP or a bug of PHP 5.2?

like image 868
Sergei Morozov Avatar asked Dec 03 '25 15:12

Sergei Morozov


1 Answers

When PHP encounters a number which doesn't fit in PHP_INT_MAX (32bits on x86), it will convert the number into a float:

If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.

Additionally, PHP 5.3 changelog says:

Changed floating point behaviour to consistently use double precision on all platforms and with all compilers. (Christian Seiler)

While I can't confirm you 100% that this is the reason for what you are seeing, I suppose it should have something to do with it.

Anyway, if you are dealing with those sorts of big numbers, you should stop relying on float precision and use an extension offering large numbers support instead, such as BC Math or GMP

like image 151
Lepidosteus Avatar answered Dec 06 '25 05:12

Lepidosteus