2016-03-10 23 views
1

我服用几个疗程机器学习,我想了解这个问题的计算:了解数值稳定性大计算损失

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

有人能告诉我为什么会发生这种情况吗?

+1

看起来像典型的浮点问题 - 计算机不能真正代表这些数字通过位,所以它变得“接近”,但你会得到一些错误和15或16位有效数字(小数点前9或10,小数点后6 )听起来符合C语言中的'float'(我通常粗略地谈论;我不知道具体情况,否则我会发布为答​​案,而不是评论)。 – dwanderson

+0

此外,为什么这个标签为'performancecounter'?这似乎与“性能”没有任何关系,而与准确性有关。 – dwanderson

+1

一些细节,以防止这个问题可以找到[这里](http://stackoverflow.com/questions/11522933/python-floatingpoint-arbitrary-precision-available)。 –

回答

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 

不断,你破坏了精度的限制,也有在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 
+0

我该如何避免这种情况?并使python数到我想要的数字? –

+0

@AlvaroJoao使用'decimal',它具有更高的精度或者不要增加'1,000,000,000'开头 – Ian

+0

@Ian我想他实际上并没有增加到10亿,然后只是减去10亿,而是提供给我们一个MCVE(尽管谁知道)。 – dwanderson

1

Python的数学本身不能公顷ndle任意精度。如果你想更精确的结果,它看起来像你需要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变成了“错误”的价值,因为它第一次在没有正规ython除10000000001e-6,它们遇到了浮点问题,然后将该值(错误)传递给Decimal - 损坏已经完成。

为您的使用情况下,它看起来像你可以使值到Decimal小号增加/减少,所以你应该得到想要的结果没有问题。

+0

thta的声音是解决这个问题的方法......谢谢 –