了解数值稳定性大的计算损失

2024-03-28 22:20:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我修了一些关于机器学习的课程,我试图理解这个计算问题:

variable = 1000000000 #1 billion
for i in xrange(1000000):
       variable = variable+ 1e-6 #0.000001

variable = variable -1000000000 #1 subtracts with 1 billion again
variable
#>> 0.95367431640625

应该是1但结果是0.95367431640625

有人能告诉我为什么会这样吗?你知道吗


Tags: in机器forwithvariable课程againxrange
2条回答

Python数学本身不能处理任意精度。如果您想得到更精确的结果,似乎需要使用decimal模块,即使这样,也要小心:

from decimal import *
x = Decimal(1000000000)
y = Decimal(1e-6)
z = x+y
z
##>> Decimal(1000000000.00000100000000000)
w = z-x
w
##>> Decimal(0.000001000000000000)

## however, when I tried:
bad_x = Decimal(1000000000 + 1e-6)
bad_x
##>> Decimal(1000000000.0000009992934598234592348593458)

bad_x变成“错误”值的原因是它首先对10000000001e-6进行了常规的ython加法,这就遇到了浮点问题,然后取了那个(错误的)值并将其传递给Decimal——损害已经造成了。你知道吗

对于您的用例,看起来您可以在加/减之前将值转换成Decimals,因此您应该可以毫无问题地获得所需的结果。你知道吗

你正在失去精确性。这是因为Python中的float实现了double floating point精度,它只能保证精度达到15/16位。你知道吗

当您这样做时:

1,000,000,000 + 0.000001
1,000,000,000.000001 + 0.000001
# and so on, note that you are adding the 16-th digit
# but 1,000,000,000.000001 is not actually exactly 1,000,000,000.000001
# behind is something like 1,000,000,000.000001014819 or 1,000,000,000.000000999819

连续不断地,您正在突破精度限制,在0.000001中的最后一个1之后还有一些其他值,它仅表示为0.000001。这样就得到了累积误差。你知道吗

如果你将你的variable初始化为0,事情会有所不同。这是因为在计算中:

0.000000 + 0.000001
0.000001 + 0.000001
0.000002 + 0.000001
#and so on

虽然0.000001的实际值并不完全是0.000001,但第16位的不精确性与有效数字相差甚远:

0.000000 + 0.00000100000000000000011111
0.000001 + 0.00000100000000000000011111 #insignificant error

也可以使用decimal值而不是double来避免错误:

from decimal import *
variable = Decimal(1000000000)
addition = Decimal(1e-6)
for i in xrange(1000000):
   variable = variable+ addition #0.000001

variable = variable-Decimal(1000000000) #1 subtracts with 1 billion again
variable

相关问题 更多 >