我试图在php中实现java的随机类,几个小时后,我发现php在将两个64位长相乘时返回的值与java的值不同。
In php
echo (int) (160577175182 * 25214903917);给出
9101091335015235584在Java小程序中
g.drawString( "Java: " + (160577175182L * 25214903917L), 10, 10 );给出
Java: 9101091335015183990有趣的是,如果您将它放入程序员模式的calc中,它也会产生9101091335015183990。
25214903917是java随机幻数0x5DEECE66D
160577175182是一个测试种子值。
我知道结果数大于64位数,因此两者的结果都是不正确的。我只需要能够在php中复制java结果。
发布于 2014-07-28 13:02:47
与mrVoid的伟大洞察力
private function java_multi($large_a,$large_b)
{
$mul_str = bcmul($large_a,$large_b);
$hex = $this->dec2hex($mul_str);
$hex = substr($hex,-16);
return (int) $this->hex2dec($hex);
}感谢乔斯特
function dec2hex($number)
{
$hexvalues = array('0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F');
$hexval = '';
while($number != '0')
{
$hexval = $hexvalues[bcmod($number,'16')].$hexval;
$number = bcdiv($number,'16',0);
}
return $hexval;
}
// Input: A hexadecimal number as a String.
// Output: The equivalent decimal number as a String.
function hex2dec($number)
{
$decvalues = array('0' => '0', '1' => '1', '2' => '2',
'3' => '3', '4' => '4', '5' => '5',
'6' => '6', '7' => '7', '8' => '8',
'9' => '9', 'A' => '10', 'B' => '11',
'C' => '12', 'D' => '13', 'E' => '14',
'F' => '15');
$decval = '0';
$number = strrev($number);
for($i = 0; $i < strlen($number); $i++)
{
$decval = bcadd(bcmul(bcpow('16',$i,0),$decvalues[$number{$i}]), $decval);
}
return $decval;
}这
java_multi(160577175182,25214903917)
返回
9101091335015183990
和java一样。
发布于 2014-07-27 16:41:05
我使用Java中的扩展算术类进行了一些测试,得出了以下结论:
PHP结果与对整数形式的未舍入输入进行乘法一致,但随后将结果转换为64位浮点。
以下结果中的所有数字都是十六进制的,因为它更容易看到正在发生的事情。
完整的产品是db7e4d92597bf73676
舍入IEEE 754 64位浮点数的产品是db7e4d92597bf80000。
Java结果是7e4d92597bf73676,是整个产品中最不重要的64位。
PHP产品为7e4d92597bf80000,是产品双转换整数值中最不重要的64位。
我不是PHP专家。PHP有扩展的整数数据类型或库吗?为了得到正确的结果,必须从产品中提取低阶64位,而不必首先转换为浮点。
发布于 2014-07-27 15:06:32
正确的结果是:4048938043477406987894
这是一个72位数。所以有一个溢出。
4048938043477406987894 mod (2^64) = 9101091335015183990部件是正确的
php实现可能是由PHP_INT_MAX舍入的,应该给出9101091335015184428。
因此,我的猜测是检查PHP_INT_MAX并将其用作for实现。
它可能也是echo (int) (160577175182 * 25214903917);和echo (int) (int)160577175182 * (int)25214903917;不同的地方
https://stackoverflow.com/questions/24982058
复制相似问题