我们有一些整数算术,由于历史原因,它必须在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?)
任何帮助将不胜感激......
答案 0 :(得分:13)
所以我解决了这个问题,并发现了很多关于PHP的问题(至少在处理Integer溢出的方式上)。
1)它完全依赖于运行机器的平台之间的交叉,PHP的哪个版本,无论是否运行Suhosin Hardened PHP,以及编译了多少位(32或64)。 6台机器按照我的预期行为(实际上是错误的,至少根据他们的文档错误)和3台机器的行为方式仍然无法解释,3台机器的行为符合intval命令所说的文档。
2)当int>时,Intval应该返回PHP_MAX_INT。 PHP_MAX_INT(不是int& 0xffffffff),但这只发生在某些版本的PHP4和PHP5上。当int>时,不同版本的PHP返回不同的值。 PHP_MAX_INT。
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来说似乎是正确的,但对于&amp; 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的30.TotBitIntval函数:
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编译器的位数。它是一个浮点数。
答案 1 :(得分:11)
如果你想在32位和64位平台上都有100%的32位intval工作解决方案,那么我建议你使用以下解决方案:
function intval32bits($value)
{
$value = ($value & 0xFFFFFFFF);
if ($value & 0x80000000)
$value = -((~$value & 0xFFFFFFFF) + 1);
return $value;
}
答案 2 :(得分:3)
在内部,PHP对大多数数字使用“整数”类型。但是,这些只是到目前为止:如果你将一个大整数添加到一个大整数,PHP将看到结果太大而不适合普通整数并将其分配给一个浮点数。然而,浮点数(浮点数)本身只是如此之高,并且在16位数字附近有一个点,PHP将完全丢失该情节。
有一个选项可以使用任意精度数学,支持任何大小和精度的数字,表示为字符串。点击此处:http://us2.php.net/bc
答案 3 :(得分:2)
我认为这可能与PHP中的整数是无符号32位有关,因为在C#中它们默认为32位。
您正在播放正常31-32位范围边缘的数字。
请参阅PHP手册中的其他文档:
http://www.php.net/manual/en/language.types.integer.php
整数的大小取决于平台,尽管最大值约为20亿是通常的值(32位有符号)。 PHP不支持无符号整数。整数大小可以使用常量PHP_INT_SIZE来确定,最大值可以使用自PHP 4.4.0和PHP 5.0.5以来的常量PHP_INT_MAX来确定。
答案 4 :(得分:2)
这会有用吗?
echo (-1580033017 + -2072974554) & 0xffffffff
总结一下,你可以做(请原谅任何语法错误,我很长时间没有触及PHP):
function s32add($a, $b) {
return ($a + $b) & 0xffffffff;
}
答案 5 :(得分:1)
检查你的PHP版本号 - 我相信你可能会得到不同版本的PHP的不同结果,这些版本可能对长整数有不同的支持。我相信在PHP 5版本的最后一个版本中存在长整数的错误。
在PHP 5.2.0版本中 - 答案与您在C#中的答案完全相同
1617621783,
利用您上面的确切功能。
您可以使用 phpinfo()命令轻松找到您的版本号。
$x1 = -1580033017;
$x2 = -2072974554;
$x3 = -1170476976 ;
$x4 = -1007518822;
echo f($x1, $x2, $x3, $x4);
function f($x1, $x2, $x3, $x4)
{
return intval(intval(intval($x1 + $x2) ^ $x3) + $x4);
}