24151.40 - 31891.10 = -7739.699999999997的MySQL&PHP小数精度错误
我抓住从一个MySQL表这两个数与类型为十进制(14,2) 24151.40 31891.10 它 精确地保存如上所述它和PHP中的完全一样。但是,当我从第一个值中减去第二个值时,我得到的数字是-7739.699999999997而不是-7,739.7。为什么要额外精确?它从哪里来?
24151.40 - 31891.10 = -7739.699999999997的MySQL&PHP小数精度错误
我抓住从一个MySQL表这两个数与类型为十进制(14,2) 24151.40 31891.10 它 精确地保存如上所述它和PHP中的完全一样。但是,当我从第一个值中减去第二个值时,我得到的数字是-7739.699999999997而不是-7,739.7。为什么要额外精确?它从哪里来?
从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,multiplication和division。
一个更好的例子
下面是同样的例子以上,但使用bcadd()函数来算一算我们。它需要三个参数。前两个是我们希望添加的值,第三个是我们希望精确到的小数位数。由于我们正在使用金钱,因此我们将精确度设置为两位十进制数。
echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be.
PHP没有像MySQL这样的小数类型,它使用浮点数;而花车因不准确而臭名昭着。
要治好这个,看看number_format
,如:
echo number_format(24151.40 - 31891.10, 2, '.', '');
为了更准确的数字操作,你也可以看看PHP的数学扩展:
这有可能采用一般的浮点/双精度率,这与科学地涉及1.FRACTAL * 2 ^指数功率有关。作为在有1前缀,有技术上没有这样的东西零,就可以获取到0最接近的值是1.0 * 2^-127是0.000000 [127 0] 00001
四舍五入你的答案到一定的精度,圆因素会给你一个更精确的答案
http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_round
有没有更好的方法来做电子商务数学? BC看起来会变得混乱。 – Anderson
真的不是很乱。只是一些确保精确数学的功能。他们使用恕我直言并不复杂。 –
这并不是说它很复杂,只是讨厌我每次需要处理金钱都必须添加此功能的事实。 – Anderson