2010-03-03 43 views
0

是否有一个时间分配之间的精密任何区别:在循环的Python:哪种方式提供了更好的精度

res=n/k 

和多任务:

for i in range(n): 
    res+=1/k 

+2

是否有实际的动机这个询问? – 2010-03-03 04:04:19

+2

应该是'范围(0,n)',不是?假设'res = 0' – Anycorn 2010-03-03 04:07:31

+0

'range(n)',你甚至可以说。 – 2010-03-03 06:36:46

回答

8

浮点除法a/b不是数学除法一个÷b,除了在极少数情况下,*。

通常,浮点除法a/b一个÷b +ε。

这是真的有两个原因。

  1. 浮点数(极少数情况除外)是十进制数的近似值。

    aa +εa。

    bb +εb。

    浮点数使用基数2编码小数点右侧的数字。当你写3.1时,这被扩展到基数2的近似值,它与实际值相差很小。顺便说一下,实数十进制数有相同的问题。写下1/3的小数点扩展。哎呀。你必须停止在某个点写小数位。二进制浮点数有同样的问题。

  2. 该分区具有固定数量的二进制位,意味着该答案被截断。如果有重复的二元模式,它会被切碎。在极少数情况下,这并不重要。一般来说,你通过分区引入了错误。

因此,当你做这样的事情反复添加1/k值你计算

ķ

以及将这些了。你的结果(如果你有正确的range)将

ñ×(1÷ķ +ε)= ñ÷ķ + ň×ε

您已经将小误差乘以n。这是一个很大的错误。 (除少数情况外)。

这很糟糕。很坏。所有的浮点除法都会引入一个错误。你作为一名程序员的工作是做代数来避免或推迟分工来防止这种情况发生。良好的软件设计意味着良好的代数,以防止分部运营商引入错误。

[*罕见的情况。在极少数情况下,小错误恰好为零。当你的浮点值是小整数或是2,1/2,1/4,1/8等幂的和的分数时,就会发生罕见的情况。在少数情况下,你的良性数与良性分数部分,错误将为零]

+0

+1:在我看来是最全面的答案。 – gorsky 2010-03-03 11:44:04

1

那么,如果kn话,肯定第一个是更准确的:-)认真地说,如果划分浮点和n > 1那么第一个会更精确,但无论如何他们可能会给出不同的结果,如nosklo说。

顺便说一句,在Python 2.6中,除法是默认情况下的整数,所以你会得到非常不同的结果。 1/k将始终给出0,除非k <= 1

+2

除非'k'是一个浮点数。 – 2010-03-03 04:03:48

0

浮点运算具有表示和舍入错误。对于数据类型的浮点数来表示,合理大小的实数,这些错误通常是可以接受的。

如果你想计算两个数的商,正确的方法是简单地说result = n/k(注意,如果这些都是整数,你没有说from __future__ import division,这不是你所期望的)。第二种方式很愚蠢,容易出错,而且很丑。

有在Python教程浮点不精确的一些讨论:http://docs.python.org/tutorial/floatingpoint.html

0

即使我们假设宽厚一个浮点除法,有精密的差别是非常明确; for循环执行n - 1次!

assert (n-1)/k != n/k 

也要看是什么res被初始化为在第二种情况下:-)

0

当然,如果你使用浮点数,除非你使用的Python解释器/编译器能够优化掉循环(也许Jython或IronPython可能能够C编译器在这方面相当不错)。

如果你真的想要这两种方法是相同的精度虽然和你正在使用的整数您的分子和分母,您可以使用Python fractions

from fractions import Fraction 
n,k = 999,1000 
res = Fraction(0,1) 

for i in range(0,n): 
    res += Fraction(1,k) 

print float(res)