【问题标题】:PHP. result of the subtraction of two floating point numbersphp。两个浮点数相减的结果
【发布时间】:2014-11-18 21:52:48
【问题描述】:

例如...

$aa = 10694994.89;
$bb = 10696193.86;
$ab = $aa - $bb;
// result is:-1198.9699999988 not the -1198,97

但是在这个例子中:

$cc = 0.89;
$dd = 0.86;
$cd = $cc - $dd;
//Result is: 0.03

为什么示例不同?缺乏精确性?

【问题讨论】:

标签: php floating-point-precision subtraction


【解决方案1】:

您的代码中没有一个数字可以准确地以二进制浮点数表示。它们都以某种方式被四舍五入。问题是为什么其中一个结果(似乎)被四舍五入到两位小数,而不是另一个。答案在于浮点数的 precisionaccuracy 与 PHP 用于打印它们的精度之间的差异。

浮点数由[1, 2) 范围内的有效数(或尾数)表示,通过乘以2 的幂来缩放。 (这就是浮点中的“浮动”的意思)。数字的精度有效位的位数决定。 准确度取决于这些数字中有多少实际上是正确的。请参阅:How are floating point numbers stored in memory? 了解更多详情。

当你在 PHP 中 echo 浮点数时,它们首先使用 precision 配置设置转换为字符串,默认为 14。(在 Zend/zend_operators.c 中)

要查看实际情况,您必须使用更高的精度打印数字:

$aa = 10694994.89;
$bb = 10696193.86;
$ab = $aa - $bb;

printf ("\$aa: %.20G\n", $aa);
printf ("\$bb: %.20G\n", $bb);
printf ("\$ab: %.20G\n\n", $ab);

$cc = 0.89;
$dd = 0.86;
$cd = $cc - $dd;

printf ("\$cc: %.20G\n", $cc);
printf ("\$dd: %.20G\n", $dd);
printf ("\$cd: %.20G\n", $cd);

输出:

$aa: 10694994.890000000596
$bb: 10696193.859999999404
$ab: -1198.9699999988079071

$cc: 0.89000000000000001332
$dd: 0.85999999999999998668
$cd: 0.030000000000000026645

初始数字的精度约为 16 到 17 位。当您减去 $aa-$bb 时,前 4 位数字相互抵消。结果(虽然仍然具有大约 16 到 17 位的精度),但现在只有准确到大约 12 位。当使用 14 位精度打印结果时,会出现这种较低的精度。

另一个减法 ($cc-$dd) 只损失一位精度,这在以 14 位精度打印时并不明显。

【讨论】:

    【解决方案2】:

    这应该适合你:

    (您必须对结果进行四舍五入!)

    $aa = 10694994.89;
    $bb = 10696193.86;
    echo $ab = round($aa - $bb, 2);
    

    【讨论】:

    • 很明显我可以四舍五入,但是为什么两个例子有区别呢?
    • 阅读我发布的链接,了解计算机如何处理浮点数
    猜你喜欢
    • 1970-01-01
    • 2015-04-13
    • 2016-05-02
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    相关资源
    最近更新 更多