【问题标题】:PHP Math fail (hexadecimal)PHP 数学失败(十六进制)
【发布时间】:2022-12-13 22:05:32
【问题描述】:

我正在尝试用 PHP 对两个 32 位长的十六进制值进行 php 乘法,它似乎搞乱了这个计算,如果我将它乘以十进制值,也会发生同样的情况。

计算如例: 0xB5365D09 * 0xDEBC252C

在使用 hexdec 之前转换为十进制不会改变任何东西。

预期结果应为 0x9DAA52EA21664A8C 但 PHP 的结果为 0x9DAA52EA21664800

例子:

<?php
$res = 0xB5365D09 * 0xDEBC252C;
echo dechex(intval($res));
?>

我在这里做错了什么?

PHP8.2 在 debian,64 位 AMD 上运行。

【问题讨论】:

  • 您没有显示任何代码。没有代码,我们无法判断您做错了什么。
  • 代码就是它应该的样子:$res = 0xAA * 0xBB;
  • 请在您的问题中添加Minimal, Reproducible Example
  • 0x9DAA52EA21664A8C 是十进制的 113609841755316742529223372036854775807 是当前的 PHP_INT_MAX。你可以试试bcmul 或类似的
  • @C.E.,我不代表 PHP 核心团队发言,但我相信一般的想法是大多数人都知道他们是否在处理大数字并且希望意识到溢出(我认为它遵循 C 的规则),而且这也是一个相对较小的群体,因此在各处添加溢出检查被认为是矫枉过正。有一个 attempt at adding arbitrarily-sized integers 到 PHP,但停滞了。

标签: php hex multiplication calculation


【解决方案1】:

所以,对于其他人来说,找到答案: 有人在我的问题的 cmets 中指出,结果超出了 PHP_MAX_INT 限制。所以当 PHP 将其作为 FLOAT 处理时,结果会丢失一些精度。我使用 bcmath 让它工作。就我而言,我没有进一步对结果进行数学计算,所以我从here 抓取了一些代码,并制作了一个简单的函数来完成我需要的事情:

function bcmul_hex($h1, $h2) {
    $dec = bcmul($h1, $h2);
    $hex = '';
    do {    
        $last = bcmod($dec, 16);
        $hex = dechex($last).$hex;
        $dec = bcdiv(bcsub($dec, $last), 16);
    } while($dec>0);
    return $hex;
}

echo bcmul_hex(0xB5365D09, 0xDEBC252C);

这是live example

【讨论】:

    【解决方案2】:

    如果你试图在 PHP 中对十六进制值执行数学运算,你可以使用 hexdec 函数将十六进制值转换为十进制值,执行运算,然后使用 dechex 函数将结果转换回十六进制值。

    这是一个例子:

       <?php
    
    $hex1 = "B5365D09";
    $hex2 = "DEBC252C";
    
    // Convert hexadecimal values to decimal
    $dec1 = hexdec($hex1);
    $dec2 = hexdec($hex2);
    
    // Perform multiplication operation
    $result = $dec1 * $dec2;
    
    // Convert result back to hexadecimal
    $hex_result = dechex($result);
    
    // Print result
    echo "Result: $hex_result
    ";
    

    此代码将乘法结果输出为十六进制值。

    【讨论】:

    • 当我插入这段代码时,我得到一个 fatal error。当我投射 float to an int 时,它修复了该错误,但是这导致与 OP 得到的数字相同。
    • 感谢您的回答。在这种情况下,乘法将返回一个浮点值,因此需要添加一个 intval($result) 或 dechex 声明才能工作。但是,正如我之前在我的问题中提到的,先转换为十进制是行不通的。看这里:3v4l.org/aJEVM
    猜你喜欢
    • 1970-01-01
    • 2021-06-08
    • 2011-09-22
    • 1970-01-01
    • 2014-05-10
    • 2017-06-09
    • 2010-10-25
    • 2015-06-25
    • 2012-04-29
    相关资源
    最近更新 更多