考虑以下代码:

0.1 + 0.2 == 0.3  ->  false
0.1 + 0.2         ->  0.30000000000000004

为什么会出现这些错误?


当前回答

浮点舍入错误。从每个计算机科学家应该知道的浮点运算:

将无限多的实数压缩成有限位数需要近似表示。虽然有无限多的整数,但在大多数程序中,整数计算的结果可以存储在32位中。相反,给定任何固定位数,大多数使用实数的计算将产生无法使用那么多位数精确表示的量。因此,浮点计算的结果必须经常舍入,以适应其有限表示。这种舍入误差是浮点计算的特征。

其他回答

它被打破的方式与你在小学学习并每天使用的十进制(以10为基础)表示法完全相同,只是以2为基础。

要理解,请考虑将1/3表示为十进制值。这是不可能做到的!世界将在你写完小数点后的3之前结束,所以我们写了一些地方,认为它足够准确。

以同样的方式,1/10(十进制0.1)不能以2为基数(二进制)精确地表示为“十进制”值;小数点后的重复模式将永远持续下去。该值不精确,因此无法使用常规浮点方法对其进行精确计算。与基数10一样,还有其他值也显示了这个问题。

我可以补充一下吗;人们总是认为这是一个计算机问题,但如果你用手(以10为基数)计算,你就不能得到(1/3+1/3=2/3)=真,除非你有无穷大可以将0.333…加到0.333……就像(1/10+2/10)一样==基数2的3/10问题,您将其截断为0.333+0.333=0.666,并可能将其舍入为0.667,这在技术上也是不准确的。

用三进制数,三分之三不是问题——也许有人会问为什么你的十进制数学被打破了。。。

存储在计算机中的浮点数由两部分组成,一部分是整数,另一部分是基数乘以整数部分的指数。

如果计算机在基数为10的情况下工作,则0.1将是1 x 10⁻¹,0.2将是2 x 10⁻¹,0.3将是3 x 10⁻¹. 整数运算简单而准确,所以加上0.1+0.2显然会得到0.3。

计算机通常不以10为基数工作,而是以2为基数工作。对于某些值,仍然可以得到精确的结果,例如0.5是1 x 2⁻¹和0.25是1 x 2⁻²,将它们相加,结果为3 x 2⁻²或0.75。确切地

问题是数字可以精确地以10为基数表示,但不能以2为基数。这些数字需要四舍五入到最接近的相等值。假设非常常见的IEEE 64位浮点格式,最接近0.1的数字是3602879701896397 x 2⁻⁵⁵, 最接近0.2的数字是7205759403792794 x 2⁻⁵⁵; 将它们相加,得到10808639105689191 x 2⁻⁵⁵, 或精确的十进制值0.30000000000000000444089209850062616169452667236328125。浮点数通常四舍五入以显示。

我刚刚看到了关于浮点数的有趣问题:

考虑以下结果:

error = (2**53+1) - int(float(2**53+1))
>>> (2**53+1) - int(float(2**53+1))
1

当2**53+1时,我们可以清楚地看到一个断点——直到2**53,所有的工作都正常。

>>> (2**53) - int(float(2**53))
0

发生这种情况的原因是双精度二进制:IEEE 754双精度二进制浮点格式:binary64

从维基百科的双精度浮点格式页面:

双精度二进制浮点是PC上常用的格式,因为它的范围比单精度浮点更广,尽管它的性能和带宽成本很高。与单精度浮点格式一样,与相同大小的整数格式相比,它缺少整数的精度。它通常简称为double。IEEE 754标准规定二进制64具有:符号位:1位指数:11位有效精度:53位(显式存储52位)具有给定偏置指数和52位分数的给定64位双精度数据假设的实际值为或

感谢@aguest向我指出了这一点。

从Python 3.5开始,您可以使用math.isclose()函数来测试近似相等性:

>>> import math
>>> math.isclose(0.1 + 0.2, 0.3)
True
>>> 0.1 + 0.2 == 0.3
False