24151.40 - 31891.10 = -7739.699999999997
我从MySQL表中获取这两个数字,类型为十进制(14,2) 24151.40 31891.10 它完全按照上面的说明保存,它与PHP中的完全相同。但是当我从第一个值中减去第二个值时,我得到一个数字-7739.699999999997而不是-7,739.7。为什么额外的精度?它来自哪里?
答案 0 :(得分: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允许您精确执行最常见的操作,包括addition,subtraction,multiplication和division。
更好的例子
这是与上面相同的例子,但是使用bcadd()函数为我们做数学运算。它需要三个参数。前两个是我们想要添加的值,第三个是我们希望精确到的小数位数。由于我们正在使用资金,因此我们将精确度设置为两位小数。
echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be.
答案 1 :(得分:1)
PHP没有像MySQL那样的十进制类型,它使用浮点数;和漂浮物因不准确而臭名昭着。
要解决此问题,请查看number_format
,例如:
echo number_format(24151.40 - 31891.10, 2, '.', '');
对于更准确的数字操作,您还可以查看PHP的数学扩展:
答案 2 :(得分:1)
这与一般浮点/双精度率有关,科学上与1.FRACTAL * 2 ^指数幂相关。因为前缀为1,所以技术上没有零,并且你可以获得的最接近的值是1.0 * 2 ^ -127,即.000000 [127 0s] 00001
通过将答案四舍五入到一定精度,圆形因子将为您提供更精确的答案
http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_round