为什么在这个方法之后,Java 和 PHP 中的结果不同,如何修复它?

huangapple go评论73阅读模式
英文:

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 &lt;&lt; 8;
    return (val3 &amp; 0xFFFFFFF) + val2 ^ (-0x10000000 &amp; val3) &gt;&gt;&gt; 24;
}

PHP code:

 function combine($val1, $val2) {
    $val3 = $val1 &lt;&lt; 8;
    return ($val3 &amp; 0xFFFFFFF) + $val2 ^ uRShift((-0x10000000 &amp; $val3), 24);
 }
 
 function uRShift($a, $b) {
    if ($a &lt; 0) 
    { 
        $a = ($a &gt;&gt; 1); 
        $a &amp;= 2147483647; 
        $a |= 0x40000000; 
        $a = ($a &gt;&gt; ($b - 1)); 
    } else { 
        $a = ($a &gt;&gt; $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 &lt;&lt; 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 &amp;= 0xFFFFFFFF;
    return $a &gt; 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 &lt;&lt; 8);
   return toSignedInt(($val3 &amp; 0xFFFFFFF) + $val2)
          ^ uRShift((-0x10000000 &amp; $val3), 24);
}

huangapple
  • 本文由 发表于 2023年2月6日 06:56:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75356072.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定