MySQL 和 PHP 小数精度错误

And*_*son 0 php mysql precision decimal

24151.40 - 31891.10 = -7739.699999999997

我从类型为decimal(14,2) 24151.40 31891.10的MySQL表中获取这两个数字,它的保存方式与上述完全相同,并且与PHP中的完全相同。但是当我从第一个值减去第二个值时,我得到一个数字 -7739.699999999997 而不是 -7,739.7。为什么要额外的精度?它来自哪里?

Joh*_*nde 5

摘自我为 Authorize.Net 撰写的一篇文章

一加一等于二,对吗?0.2 加 1.4 乘以 10 怎么样?这等于 16,对吧?如果您使用 PHP(或大多数其他编程语言)进行数学计算,则不然:

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

这是由于浮点数的内部处理方式决定的。它们以固定的小数位数表示,并且可能会导致数字加起来与您预期的不太一样。在内部,我们的 .2 加 1.4 乘以 10 示例计算得出大约 15.9999999998 左右。当处理不需要像百分比这样精确的数字时,这种数学方法很好。但是,在处理金钱问题时,精确性很重要,因为这里或那里丢失的一分钱或一美元很快就会加起来,没有人喜欢因为丢失的钱而受到损失。

BC 数学解决方案

幸运的是,PHP 提供了BC Math 扩展,它“对于任意精度的数学,PHP 提供了二进制计算器,它支持任何大小和精度的数字,以字符串表示。” 换句话说,您可以使用此扩展对货币值进行精确的数学计算。BC Math 扩展包含允许您精确执行最常见运算的函数,包括加法减法乘法除法

更好的例子

这是与上面相同的示例,但使用 bcadd() 函数为我们进行数学计算。它需要三个参数。前两个是我们希望添加的值,第三个是我们希望精确到的小数位数。由于我们使用的是金钱,因此我们将精度设置为小数点后两位。

echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be.
Run Code Online (Sandbox Code Playgroud)