如果仍然有人点击此页面时遇到类似的问题,其中浮点数减法导致错误或奇怪的值。下面我将更详细地解释这个问题。
它与PHP没有直接关系,也不是一个错误。但是,每个程序员都应该意识到这个问题。
这个问题甚至在二十年前夺走了许多生命。
1991年2月25日,MIM-104爱国者导弹电池中的一个不正确的浮点运算(称为四舍五入误差)阻止它在沙特阿拉伯达兰拦截一枚来袭的飞毛腿导弹,造成美国陆军第14军需分遣队的28名士兵死亡,近100名军人受伤。
但为什么会发生这种情况呢?
原因是浮点值表示的精度有限。因此,值在进行任何处理(切掉)后可能不具有相同的字符串表示形式。它还包括在脚本中编写浮点值,并在没有任何数学运算的情况下直接打印它。
举个简单的例子:
$a = '36';
$b = '-35.99';
echo ($a + $b);
你会期望它打印出来,对吧?但它会打印一个非常奇怪的答案,比如0.01
0.009999999999998
与其他数字一样,浮点数双精度或浮点数作为 0 和 1 的字符串存储在内存中。浮点数与整数的区别在于当我们想要查看0和1时,我们如何解释它们。它们的存储方式有很多标准。
浮点数通常作为符号位、指数场以及有效数或尾数(从左到右)打包到计算机数据中。
由于缺乏足够的空间,十进制数在二进制中不能很好地表示。所以,你不能完全按照它本来的样子表达,对吧?为什么我们不能表示为二进制浮点数也是出于同样的原因。 带有重复。1/3
0.3333333...
0.01
1/100
0.00000010100011110101110000.....
10100011110101110000
如果以二进制的简化和系统截断形式保存,当它被转换回十进制时,它将根据系统被读取(64位计算机将为您提供比32位更好的精度)。在这种情况下,操作系统决定是按它所看到的方式打印它,还是如何以更人性化的方式制作它。因此,这取决于他们想要如何表示它取决于机器。但它可以用不同的方法在语言层面上得到保护。0.01
01000111101011100001010
0.0099999....
如果使用
echo number_format(0.009999999999998, 2);
它将打印.0.01
这是因为在这种情况下,您指示应如何读取它以及所需的精度。
注意 number_format() 不是唯一的函数,可以使用其他一些函数和方法告诉编程语言有关精度期望的信息。
参考资料:
https://sdqweb.ipd.kit.edu/publications/pdfs/saglam2016a.pdf
https://en.wikipedia.org/wiki/Round-off_error