1e-11 的 Python 浮点精度的奇怪行为

Strange behaviour of Python floating point precision for 1e-11

使用 python 2.7.17 或 3.6.9 时,使用值“1e11”时会出现奇怪的行为。 对于两个版本:

>>> 1.0e-11*1.0e11

0.9999999999999999

>>> 1.0e-10*1.0e10

1.0


>>> 1.0e-12*1.0e12

1.0

>>> 1.0e-13*1.0e13

1.0

etc.

>>> 1.0-(1.0e-11*1.0e11)

1.1102230246251565e-16

同时,对于所有其他指数 [编辑:20 以下],结果正确为 0.0。显然存在一些浮点精度问题,但为什么指数 10、11 和 12 之间不一致。这是怎么回事?

Floating-point numbers are represented in computer hardware as base 2 (binary) fractions.

Unfortunately, most decimal fractions cannot be represented exactly as binary fractions. A consequence is that, in general, the decimal floating-point numbers you enter are only approximated by the binary floating-point numbers actually stored in the machine.

If you’re in a situation where you care which way your decimal halfway-cases are rounded, you should consider using the decimal module. Incidentally, the decimal module also provides a nice way to “see” the exact value that’s stored in any particular Python float

As that says near the end, “there are no easy answers.” Still, don’t be unduly wary of floating-point! The errors in Python float operations are inherited from the floating-point hardware, and on most machines are on the order of no more than 1 part in 2**53 per operation. That’s more than adequate for most tasks, but you do need to keep in mind that it’s not decimal arithmetic, and that every float operation can suffer a new rounding error.