一次性作业之间的精确度是否存在差异:
res=n/k
和for循环中的多个赋值:
for i in range(n):
res+=1/k
答案 0 :(得分:8)
浮点除法a/b
不是数学除法 a ÷ b ,除非是非常罕见的情况。
通常,浮点除a/b
是 a ÷ b +ε。
这有两个原因。
浮点数(极少数情况除外)是十进制数的近似值。
a
a +εa。
b
b +εb。
浮点数使用小数点右侧数字的基数2编码。当您编写3.1
时,会将其扩展为基数2近似值,该值与实际值略有不同。
顺便说一下,实数十进制数有同样的问题。记下1/3的十进制扩展。哎呀。你必须在某个时候停止写小数位。二进制浮点数具有相同的问题。
Division具有固定数量的二进制位,意味着答案被截断。如果有重复的二进制模式,它会被切断。在极少数情况下,这无关紧要。一般来说,你通过分裂引入了错误。
因此,当您执行重复添加1/k
值的操作时,您正在计算
1÷ 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
答案 2 :(得分:1)
如果k
除n
那么肯定第一个更精确:-)严肃来说,如果除法是浮点而n > 1
那么第一个将更多尽管如此,尽管他们可能会给出不同的结果,正如nosklo所说的那样。
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)