我们有一些整数算法,由于历史原因,它必须在PHP上与在几种静态类型的语言中相同。自从我们上次升级PHP以来,溢出整数的行为已更改。基本上,我们使用以下公式:
function f($x1, $x2, $x3, $x4) { return (($x1 + $x2) ^ $x3) + $x4; }
但是,即使进行了转换:
function f($x1, $x2, $x3, $x4) { return intval(intval(intval($x1 + $x2) ^ $x3) + $x4); }
我仍然以完全错误的数字结尾…
例如,在$ x1 = -1580033017,$ x2 = -2072974554,$ x3 = -1170476976和$ x4 = -1007518822的情况下,我最终在PHP中使用-30512150,在C#中使用1617621783。
仅仅将$ x1和$ x2加在一起,我无法得到正确的答案:
在C#中我得到
(-1580033017 + -2072974554) = 641959725
在PHP中:
intval(intval(-1580033017) + intval(-2072974554)) = -2147483648
与以下内容相同:
intval(-1580033017 + -2072974554) = -2147483648
我不介意编写“ IntegerOverflowAdd”函数之类的东西,但我不太想知道(-1580033017 + -2072974554)等于641959725。(我确实知道它是-2147483648 +(2 * 2 ^ 31) ,但-2147483648 + 2 ^ 31是-1505523923,它大于Int.Min,所以为什么要加上2 * 2 ^ 31而不是2 ^ 31?)
任何帮助,将不胜感激…
因此,我解决了这个问题,并发现了很多有关PHP的知识(至少在处理Integer溢出的方式方面)。
1)它完全取决于机器在哪个平台上运行,哪个版本的PHP,是否运行Suhosin Hardened PHP以及为多少(32或64)位编译之间的交叉。6台计算机的行为符合我的预期(实际上是错误的,至少根据他们的文档是错误的),而3台计算机的行为依旧无法解释,而3台计算机的行为则是根据intval命令说的来完成的。文档。
2)当int> PHP_INT_MAX(不是int和0xffffffff)时,Intval应该返回PHP_INT_MAX,但这仅在某些版本的PHP4和PHP5上发生。当int> PHP_INT_MAX时,不同版本的PHP返回不同的值。
3)以下代码可以返回3个不同的结果(请参见1):
<?php echo "Php max int: ".PHP_INT_MAX."\n"; echo "The Val: ".(-1580033017 + -2072974554)."\n"; echo "Intval of the val: ".intval(-3653007571)."\n"; echo "And 0xffffffff of the val: ".(-3653007571 & 0xffffffff)."\n"; ?>
它可以返回(对于Intval似乎正确,但对于&0xffffff则错误)
Php max int: 2147483647 The Val: -3653007571 Intval of the val: -2147483648 And of the val: -2147483648
它可以返回(与intval的PHP文档相矛盾):
Php max int: 2147483647 The Val: -3653007571 Intval of the val: -641959725 And of the val: -641959725
在64位计算机上,它返回(正确):
Php max int: 2147483647 The Val: -3653007571 Intval of the val: -3653007571 And of the val: -641959725
解
无论如何,我需要一个适用于所有这些平台的解决方案,并且不依赖于使用特定Max int编译的特定版本PHP的怪癖。因此,我总结了以下跨PHP的threenTwoBitIntval函数:
function thirtyTwoBitIntval($value) { if ($value < -2147483648) { return -(-($value) & 0xffffffff); } elseif ($value > 2147483647) { return ($value & 0xffffffff); } return $value; }
评论
我确实认为PHP的设计师应该说一个Int是32位Int,无论它是在32位,64位还是128位计算机上运行(例如DotNet CLR),并且没有将其随机上转换为浮动取决于PHP编译器所依据的位数。