2012-03-03 177 views
1

可能重复:
Strange addition of numeric strings in PHP奇怪的行为

$r = 1.0 - 0.8 - 0.2; 
var_dump($r); 

我得到浮动-5.5511151231258E-17。 我在C++和C#中获得的结果相同。

的MySQL我得到通过查询产生的0.0:

SELECT 1.0 - 0.8 - 0.2 
+0

*一般参考的问题* http://php.net/manual/en/language.types.float.php – NikiC 2012-03-03 14:28:33

+0

另外:HTTP://en.wikipedia。组织/维基/ Floating_point#Accuracy_problems – Leigh 2012-03-03 14:33:12

回答

8

让它成为明确:0.8在十进制有限表示,因为它的价值8/10¹

但在基数2中,其值为:1/2 + 1/4 + 0/8 + 0/16 + 1/32 + 1/64 + 0/128 + ...并且它没有结束,像三分之一具有十进制表示(0.333…)没有结束,但将在0.1基座3

0.8 = 0.110011001100110011001100... in binary 
0.2 = 0.001100110011001100110011... in binary 

笔记本计算机存储浮点值的二进制表示。因此,当您添加,减去,乘数等数字时,会出现精度损失。

C++,C和C#是编译语言,浮点数通常是4或8字节。你不能将0.8存储在浮动中。

MySQL可能会告诉你0,因为它会截断计算结果。

如果您想要一个在任何基础上执行计算而不损失精度的库,请查找GMPlib。

3

您可以通过使用BCMath(此例为bcsub())来避免它。或者你可以简单地round()(注意你可以设置第二个参数的精度)。对于所有情况下,您将收到-0,如果您需要积极0只使用abs()

看看我说的here

代码示例

<?php 

    echo 'Direct: ' . (1.0 - 0.8 - 0.2) . '<br/>'; 

    echo 'BC Math: ' . bcsub(bcsub('1.0', '0.8'), '0.2') . '<br/>'; 
    echo 'Round: ' . round(1.0 - 0.8 - 0.2) . '<br/>'; 
    echo 'Absolute: ' . abs(round(1.0 - 0.8 - 0.2)) . '<br/>'; 

?>