有时我们进行一些简单的数学运算,可能会遇到不符合预期的结果。比如,用 Python 计算 1.2 - 1.0
时,你可能期望得到 0.2
,但实际结果却是 0.19999999999999996
。这看起来很奇怪,甚至会让人怀疑是不是 Python 出了问题。但实际上,这不是 Python 的问题,而是计算机处理小数的方式所导致的。
计算机如何存储数字
在大多数编程语言中,包括 Python,用来表示小数的数据类型叫做“浮点数”。Python 使用了一种叫做“双精度浮点数”的格式来储存这些数值,这种格式是由 C 语言定义的,并且被很多其他编程语言所采用。双精度浮点数能够非常精确地表示一定范围内的数字,但它涉及到十进制的小数时,处理起来会比较复杂。
十进制与二进制之间的转换
我们通常使用的是十进制系统,但是计算机内部使用的是二进制系统。有些十进制小数可以很容易地转换成有限位数的二进制小数,比如 0.5 可以写成 0.1 (二进制)。然而,像 0.2 这样的十进制小数却不能精确地用有限个二进制位来表示;它会成为一个无限重复的二进制小数。因此,当我们告诉计算机去储存一个像 1.2
这样的值时,它实际上必须找到最接近的、可以用有限个二进制位表示的数值。
1.2 在计算机中的表示
当你输入 x = 1.2
到 Python 中,计算机将 1.2
存储为一个近似的二进制数:
1.0011001100110011001100110011001100110011001100110011... (二进制)
这个二进制数对应于一个稍微不同于 1.2 的十进制数:
1.1999999999999999555910790149937383830547332763671875
虽然看起来和 1.2 很接近,但并不完全相同。这就是为什么当你执行减法操作如 1.2 - 1.0
时,得到的结果并不是精确的 0.2
。
浮点数的精度限制
由于浮点数是通过固定数量的二进制位来表示的(通常是 53 位),它们只能提供大约 15 到 16 位小数的精度。对于大多数应用来说,这样的精度已经足够了,但在某些需要极高精度的情况下,就需要使用专门的高精度库或数据类型。