英文:
Why after this method the result is different in Java and PHP and how to fix it?
问题
在较小的数值下,这种方法在Java和Python中能够正确工作,但在较大的数值下,结果会不同。问题出在哪里,以及如何修复它?
Java 代码:
private static int combine(int val1, int val2) {
int val3 = val1 << 8;
return (val3 & 0xFFFFFFF) + val2 ^ (-0x10000000 & val3) >>> 24;
}
PHP 代码:
function combine($val1, $val2) {
$val3 = $val1 << 8;
return ($val3 & 0xFFFFFFF) + $val2 ^ uRShift((-0x10000000 & $val3), 24);
}
function uRShift($a, $b) {
if ($a < 0)
{
$a = ($a >> 1);
$a &= 2147483647;
$a |= 0x40000000;
$a = ($a >> ($b - 1));
} else {
$a = ($a >> $b);
}
return $a;
}
例如,如果在这两种方法中插入这些数字 combine(125,107)
,Java 和 PHP 的结果将是相同的(32107)。如果我使用较大的数字,比如 combine(287651245, 107)
,Java 的结果是87403851,而 PHP 的结果是87407691。我怀疑左移操作可能有问题。
英文:
With smaller numbers, this method works correctly in Java and Python, but with larger numbers, the result is different. What is the problem and how can I fix it?
Java code:
private static int combine(int val1, int val2) {
int val3 = val1 << 8;
return (val3 & 0xFFFFFFF) + val2 ^ (-0x10000000 & val3) >>> 24;
}
PHP code:
function combine($val1, $val2) {
$val3 = $val1 << 8;
return ($val3 & 0xFFFFFFF) + $val2 ^ uRShift((-0x10000000 & $val3), 24);
}
function uRShift($a, $b) {
if ($a < 0)
{
$a = ($a >> 1);
$a &= 2147483647;
$a |= 0x40000000;
$a = ($a >> ($b - 1));
} else {
$a = ($a >> $b);
}
return $a;
}
For example, if in both methods I insert these numbers combine(125,107)
, the result in Java and PHP will be the same (32107). If I put in a larger number, like combine(287651245, 107)
, the result for Java is 87403851 and for PHP it is 87407691. I suspect there is something wrong with the left shifting.
答案1
得分: 1
Today most of PHP releases are x64 builds, that means integers are 64-bit long, so the result of this arithmetic $val3 = $val1 << 8;
is a 64-bit integer.
In Java you forced the result to be a signed 32-bit integer int
, the left shift operator automatically cut off the exceeded bits, but in PHP it won't, so you need do it manually.
function toSignedInt($a) {
if(PHP_INT_SIZE == 4) return $a;
$a &= 0xFFFFFFFF;
return $a > 2147483647 ? $a - 4294967296 : $a;
}
You need be carefull in every places of overflow and wrap them with this function. In this code, they are the left shift operator and the add operator.
function combine($val1, $val2) {
$val3 = toSignedInt($val1 << 8);
return toSignedInt(($val3 & 0xFFFFFFF) + $val2)
^ uRShift((-0x10000000 & $val3), 24);
}
英文:
Today most of PHP releases are x64 builds, that means integers are 64-bit long, so the result of this arithmetic $val3 = $val1 << 8;
is a 64-bit integer.
In Java you forced the result to be a signed 32-bit integer int
, the left shift operator automatically cut off the exceeded bits, but in PHP it won't, so you need do it manually.
function toSignedInt($a) {
if(PHP_INT_SIZE == 4) return $a;
$a &= 0xFFFFFFFF;
return $a > 2147483647 ? $a - 4294967296 : $a;
}
You need be carefull in every places of overflow and wrap them with this function. In this code, they are the left shift operator and the add operator.
function combine($val1, $val2) {
$val3 = toSignedInt($val1 << 8);
return toSignedInt(($val3 & 0xFFFFFFF) + $val2)
^ uRShift((-0x10000000 & $val3), 24);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论