我参加了一些关于机器学习的课程,并试图理解这个计算问题:
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
有人可以告诉我为什么会这样吗?
答案 0 :(得分:4)
你正在失去精确度。这是因为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
接下来,您违反了精度限制,1
中的最后一个0.000001
后面还有一些其他值,仅代表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
答案 1 :(得分:1)
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
成为“错误”值的原因是因为它首先在1000000000
和1e-6
上进行了常规ython添加,遇到浮点问题,然后接受了(错误的)并将其传递给Decimal
- 损坏已经完成。
对于您的用例,看起来您可以在添加/减去之前将值设置为Decimal
s ,这样您就可以毫无问题地获得所需的结果。