Php 为什么我从两个假定相似的算术运算中得到不同的结果?

Php 为什么我从两个假定相似的算术运算中得到不同的结果?,php,php-5.4,Php,Php 5.4,在下面的代码中,为什么乘法方法不会产生舍入错误,而累积加法会产生舍入错误 function get_value() { return 26.82; } function a($quantity) { $value_excluding_vat = get_value(); $value_including_vat = round($value_excluding_vat * (1 + (20 / 100)),2); $total_nett = 0; $total_

在下面的代码中,为什么乘法方法不会产生舍入错误,而累积加法会产生舍入错误

function get_value() { return 26.82; }

function a($quantity) {
    $value_excluding_vat = get_value();
    $value_including_vat = round($value_excluding_vat * (1 + (20 / 100)),2);
    $total_nett = 0;
    $total_gross = 0;
    for($i=0; $i<$quantity; $i++) {
        $total_nett += $value_excluding_vat;
        $total_gross += $value_including_vat;
    }
    return array(
        $total_nett,
        $total_gross
    );
}

function b($quantity) {
    $value_excluding_vat = get_value();
    $value_including_vat = round($value_excluding_vat * (1 + (20 / 100)),2);
    return array(
        $quantity * $value_excluding_vat,
        $quantity * $value_including_vat
    );
}

$totals = a(1000);
print_r($totals);
echo $totals[1] - $totals[0];
echo "\n\n";
$totals = b(1000);
print_r($totals);
echo $totals[1] - $totals[0];
问题可能存在(请参见警告块)

e、 g.21470.73可能是21470.729999..9994561或21470.73000…0001231,取决于它们是如何计算的


在计算
$total

之前,尝试对临时值进行四舍五入,例如
gross\u total\u so\u far
nett\u total\u so\u far
我猜不出浮点数表示和减法的问题,但是

在不进行四舍五入的情况下减去这些值,将得到结果**3578.455

当您将其四舍五入到小数点后两位时,它将以3578.46四舍五入

所以php有一个解决这个问题的方法

PHP_ROUND_HALF_UP   Round val up to precision decimal places away from zero,    when it is half way there. Making 1.5 into 2 and -1.5 into -2.

PHP_ROUND_HALF_DOWN     Round val down to precision decimal places towards zero, when it is half way there. Making 1.5 into 1 and -1.5 into -1.

PHP_ROUND_HALF_EVEN     Round val to precision decimal places towards the next even value.

PHP_ROUND_HALF_ODD  Round val to precision decimal places towards the next odd value.
这些常数以四舍五入函数形式提供

echo round(100.675, 2, PHP_ROUND_HALF_UP);   // 100.68
echo round(100.675, 2, PHP_ROUND_HALF_DOWN); // 100.67

S>强>PHPrOrth-LoopixLoad

>对于你的情况

是有用的,首先,考虑在基10中有许多是有理数的,而不是二进制浮点表示中的数。例如,26.82的浮点值实际上是

26.8200000000000002842170943040400743484497

当然,如果您不断地将其添加到自身中,会出现一些错误,但最多可以添加15个有效数字-将其添加1000次,总数实际上是
26819.9999997671693563461303710937500000000

有趣的问题是,当我们将26.82乘以1000.0时,我们得到的是
26820.0000000000000000000000000000000000000000
——它是如何做到的

答案很简单,26820.0确实有一个精确的二进制表示,乘法运算足够聪明,可以发现这一点——即使乘以1001.0,减去26.82,仍然可以得到精确的答案

这里有几个有趣的链接

  • -这使您可以查看浮点数的单精度表示,并有助于真正理解浮点数
  • 这非常有趣,因为它涵盖了围绕舍入浮动的一些问题

可能重复的我将您的问题理解为:“我有代码A(未显示),它在对浮点数进行乘法和舍入时返回结果X。我将其更改为代码B(未显示),它生成结果Y。为什么会发生这种情况?”。答案是:这取决于您的代码,可能与舍入错误有关。请显示您的实际、相关代码和您所尝试的。考虑使用$MODE参数:默认为PHPyTrangWalpUILUPUP(如果函数太长而不能显示),那么您重构了什么?你期望得到什么样的答案?您更改了一些代码,使输出变得不同,因此问题在于您更改了什么。在没有显示您所更改的内容的情况下,除了我所说的之外,没有什么用处:看起来像是浮点舍入错误。稍微了解一下可能发生的情况后,我明白了您的观点。我找到了一种复制我所看到的东西的方法,并且完全修改了这个问题——相比之下,原来的问题确实是垃圾——道歉。
echo round(100.675, 2, PHP_ROUND_HALF_UP);   // 100.68
echo round(100.675, 2, PHP_ROUND_HALF_DOWN); // 100.67