PHP Float Subtract

时间:2018-02-07 09:18:19

标签: php numbers php-5.6

我有这个简单的减法代码:

<?php
    $n1 = 257931.076;
    $n2 = 257930;

    echo $n1 - $n2;
?>

为什么我得到1.0760000000009而不是1.076

0000000009来自哪里?我需要准确的结果而且我不想使用round()number_format()因为有时我的小数超过3,例如: 12345.678912,有人知道吗?

我尝试使用round()number_format(),但它仅用于固定的小数点,而不是动态的

2 个答案:

答案 0 :(得分:1)

由于every programmer should be aware of的技术原因,IEEE浮点数不能精确地表示数字,并且将使用它们在存储时最接近的近似值(实际上,可以完美存储的唯一分数具有分母2的幂(1 / 2,1 / 4,1 / 8,1 / 16等等。所有其他值都是近似值。)PHP有一个称为“精度”的ini值,它控制被认为有多少位数当输出浮点值时。默认为14,隐藏后的任何数字。

但是,存储的实际值可能会尝试使用远远多于其的数字来近似所需的值。如果更改精度,您将看到实际存储的内容。

php > $test = 0.1;
php > var_dump ($test);
php shell code:1:
double(0.1)
php > ini_set("precision", 100);
php > var_dump ($test);
php shell code:1:
double(0.1000000000000000055511151231257827021181583404541015625)
php > var_dump (0.25);
php shell code:1:
double(0.25)
php > var_dump (0.4);
php shell code:1:
double(0.40000000000000002220446049250313080847263336181640625)

你真的可以做些什么?不是很多,这只是浮点运算的结果。如果您需要确切的值,可以尝试避免使用浮点数(例如,当处理金额时,将3.99存储为399便士/美分而不是3.99磅/美元),或者您可以使用可用的“bugnum”库PHP,GMP和BC_Math,但这些都很难使用,并有自己的陷阱集。它们在存储和/或处理器时间上也很难。在大多数情况下,最好只使用它并注意当你处理浮点时你没有处理精确的表示。

答案 1 :(得分:1)

正如@GordonM完美解释的那样,使用浮点值时无法获得准确的结果。

您可以使用brick/math等库对任意大小的十进制数进行精确计算:

use Brick\Math\BigDecimal;

$n1 = BigDecimal::of('257931.076'); // pass the number as a string to retain precision!
$n2 = 257930;

echo $n1->minus($n2); // 1.076

库在可用时在内部使用GMP或BCMath,但也可以在没有这些扩展的情况下工作(性能损失)。