Python:哪种方式可以提供更好的精度

时间:2010-03-03 03:52:52

标签: python precision

一次性作业之间的精确度是否存在差异:

res=n/k

和for循环中的多个赋值:

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

6 个答案:

答案 0 :(得分:8)

浮点除法a/b不是数学除法 a ÷ b ,除非是非常罕见的情况。

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

这有两个原因。

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

    a a +εa。

    b b +εb。

    浮点数使用小数点右侧数字的基数2编码。当您编写3.1时,会将其扩展为基数2近似值,该值与实际值略有不同。

    顺便说一下,实数十进制数有同样的问题。记下1/3的十进制扩展。哎呀。你必须在某个时候停止写小数位。二进制浮点数具有相同的问题。

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

  3. 因此,当您执行重复添加1/k值的操作时,您正在计算

    k

    然后加上这些。您的结果(如果您有正确的range)将是

    n ×(1÷ k +ε)= n ÷ k + n < / em>×ε

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

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

    [*极少数情况。在极少数情况下,小错误恰好为零。罕见的情况发生在您的浮点值是小的整数或分数,即两个1 / 2,1 / 4,1 / 8等的幂的总和。在极少数情况下,您有一个良性数字与良性分数部分,错误将为零。]

答案 1 :(得分:3)

当然,它们是不同的,因为浮点除法如何运作。

>>> res = 0
>>> for x in xrange(5000): res += 0.1
... 
>>> res == 5000 * 0.1
False

a good explanation in the python official tutorial

答案 2 :(得分:1)

如果kn那么肯定第一个更精确:-)严肃来说,如果除法是浮点而n > 1那么第一个将更多尽管如此,尽管他们可能会给出不同的结果,正如nosklo所说的那样。

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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

即使我们慈善地假设一个浮点除法,但精确度肯定存在差异; for循环执行n - 1次!

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

还取决于在第二种情况下初始化res的内容: - )

答案 5 :(得分: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)