Python:哪种方法更精确

0 投票
6 回答
510 浏览
提问于 2025-04-15 19:56

一次性赋值和在循环中多次赋值之间,精度上有没有什么区别呢?

res=n/k

还有在循环里进行多次赋值的情况:

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

这两者之间有什么不同吗?

6 个回答

1

如果 k 能整除 n,那么第一个方法肯定更准确 :-) 说正经的,如果是浮点数的除法,而且 n > 1,那么第一个方法无论如何都会更精确,尽管它们可能会给出不同的结果,就像nosklo说的那样。

顺便提一下,在Python 2.6中,除法默认是整数除法,所以你会得到非常不同的结果。 1/k 只要 k <= 1,结果才会是非零的,其他情况下结果总是0。

3

当然,它们是不同的,因为浮点数除法的工作方式不同。

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

Python官方教程中,有一个很好的解释。

8

浮点数的除法 a/b 和数学上的除法 a ÷ b 并不是完全一样的,只有在非常少见的情况下才会相同。

通常情况下,浮点数的除法 a/b 实际上是 a ÷ b 加上一个小误差 ε。

这个情况有两个原因。

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

    a 实际上是 a 加上一个小误差 εa。

    b 实际上是 b 加上一个小误差 εb。

    浮点数使用的是二进制来表示小数点右边的数字。当你写 3.1 时,它会被转换成一个二进制的近似值,这个近似值和真实值之间会有一点小差别。

    顺便说一下,真实的十进制数也有同样的问题。比如写下 1/3 的十进制展开,哎呀,你必须在某个地方停止写小数位。二进制浮点数也有同样的问题。

  2. 除法有固定的二进制位数,这意味着结果会被截断。如果有重复的二进制模式,它会被切掉。在极少数情况下,这个问题不大。一般来说,进行除法时就会引入误差。

因此,当你像这样反复加 1/k 的值时,你实际上是在计算

1 ÷ k 加上一个小误差 ε。

然后把这些值加起来。如果你有正确的 range,你的结果会是

n × (1 ÷ k + ε) = n ÷ k + n × ε

你把这个小误差 ε 乘以了 n,结果就变成了一个大误差。(除了极少数情况。)

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

[* 极少数情况。在极少数情况下,小误差恰好为零。这种情况发生在你的浮点值是小的整数或是 1/2、1/4、1/8 等的和时。如果你碰巧有一个没有问题的数字和没有问题的小数部分,那么误差就是零。]

撰写回答