2012-05-04 36 views
0

24151.40 - 31891.10 = -7739.699999999997的MySQL&PHP小数精度错误

我抓住从一个MySQL表这两个数与类型为十进制(14,2) 24151.40 31891.10 它 精确地保存如上所述它和PHP中的完全一样。但是,当我从第一个值中减去第二个值时,我得到的数字是-7739.699999999997而不是-7,739.7。为什么要额外精确?它从哪里来?

回答

4

an article I wrote for Authorize.Net

一加一等于二,对吧?怎么样.2加1.4次10?那等于16,对吗?若你正在做与PHP(或大多数其他编程语言)数学:

echo floor((0.2 + 1.4) * 10); // Should be 16. But it's 15! 

这是由于点如何浮点数的内部处理。它们以固定的小数位数表示,并且可能会导致数字与您预期的不相符。在我们的内部,我们的.2加1.4倍10个例子的计算大致为15.9999999998左右。使用不需要精确到百分比的数字时,这种数学方法很好。但是,当处理金钱精确性问题时,如果一分钱或者一美元在这里或者那里失踪,就会很快加起来,而且没有人喜欢在缺少资金的情况下进行短期融资。

的BC数学解

好在PHP提供BC Math extension这是“为任意精度数学PHP提供支持的任何尺寸和精度,表示为字符串的号码二进制计算器”。换句话说,你可以用这个扩展名用货币值做精确的数学运算。 BC Math extension contains function s允许您以精确度执行最常见的操作,包括addition,subtraction,multiplicationdivision

一个更好的例子

下面是同样的例子以上,但使用bcadd()函数来算一算我们。它需要三个参数。前两个是我们希望添加的值,第三个是我们希望精确到的小数位数。由于我们正在使用金钱,因此我们将精确度设置为两位十进制数。

echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be. 
+0

有没有更好的方法来做电子商务数学? BC看起来会变得混乱。 – Anderson

+0

真的不是很乱。只是一些确保精确数学的功能。他们使用恕我直言并不复杂。 –

+0

这并不是说它很复杂,只是讨厌我每次需要处理金钱都必须添加此功能的事实。 – Anderson

1

PHP没有像MySQL这样的小数类型,它使用浮点数;而花车因不准确而臭名昭着。

要治好这个,看看number_format,如:

echo number_format(24151.40 - 31891.10, 2, '.', ''); 

为了更准确的数字操作,你也可以看看PHP的数学扩展:

http://www.php.net/manual/en/refs.math.php

+0

哇真的吗?反正有十进制类型存储到MySQL表中,不需要我每次使用从MySQL中选择的值时使用number_format? – Anderson

+0

@Anderson你可以从MySQL中检索而不必做任何事情;只有在操作(添加/减去)该值并需要将其写回数据库后才需要它。事实上,当它出来的MySQL它仍然是一个字符串:) –

+0

所以这会发生,即使我将字符串转换为数字? – Anderson