PHP bcmath与Python Decim

2024-09-30 14:16:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用PHP的bcmath库对定点数字执行操作。我本来希望得到Python的Decimal类的相同行为,但是我很惊讶地发现以下行为:

// PHP:
$a = bcdiv('15.80', '483.49870000', 26);
$b = bcmul($a, '483.49870000', 26);
echo $b;  // prints 15.79999999999999999999991853

在Python中使用Decimals时,我得到:

^{pr2}$

为什么?由于我使用它来执行非常敏感的操作,所以我想找到一种在PHP中获得与Python相同的结果的方法(即(x / y) * y == x


Tags: 方法echo数字prints定点phpdecimalpr2
1条回答
网友
1楼 · 发布于 2024-09-30 14:16:40

经过一番实验,我终于明白了。这是舍入与截断的问题。默认情况下,Python使用ROUND_HALF_EVEN取整,而PHP只是以指定的精度截断。Python的默认精度是28,而在PHP中使用的是26。在

In [57]: import decimal
In [58]: decimal.getcontext()
Out[58]: Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[InvalidOperation, Overflow, DivisionByZero])

如果您想让Python模仿PHP的截断行为,只需更改rounding属性:

^{pr2}$

让PHP的行为像Python的默认值有点困难。我们需要为除法和乘法创建一个自定义函数,它像Python一样取整“半偶数”:

function bcdiv_round($first, $second, $scale = 0, $round=PHP_ROUND_HALF_EVEN)
{
    return (string) round(bcdiv($first, $second, $scale+1), $scale, $round);
}

function bcmul_round($first, $second, $scale = 0, $round=PHP_ROUND_HALF_EVEN)
{
    $rounded = round(bcmul($first, $second, $scale+1), $scale, $round);

    return (string) bcmul('1.0', $rounded, $scale);
}

下面是一个演示:

php > $a = bcdiv_round('15.80', '483.49870000', 28);
php > $b = bcmul_round($a, '483.49870000', 28);
php > var_dump($b);
string(5) "15.80"

相关问题 更多 >

    热门问题