我正在尝试将 MATLAB 脚本的数值输出与 numpy 的数值输出进行比较。
家庭作业中的任务是将 10^-N 的值与其自身相加 10^N 次。
我们的目标是证明计算机在这种计算中存在局限性。结果应该始终为1,但随着N的增加,误差也会增加。对于这个问题,N 应该是 0, 1, 2, ..., 8。
我的 MATLAB 脚本运行速度很快,没有任何问题:
solns = zeros(1, 9);
for N = 0:8
for ii = 1:(10^N)
solns(N+1) = solns(N+1) + 10^-N;
end
end
但是,在带有 numpy 的 Anaconda 安装上使用 Python 3.8.12,此代码将不会终止(请参阅更新,代码确实会执行):
import numpy as np
solns = np.zeros((9, 1))
for N in range(len(solns)):
for _ in range(10**N):
solns[N] += (10**-N)
Python 代码中是否存在错误,或者创建此结果的语言之间是否存在某些显着差异。
编辑:
我让 python 代码运行了一段时间,它最终在 230 秒后终止。整个数组打印为 [1., 1., 1., 等等]。
仅供引用,在 MATLAB 上使用 tic
toc
命令,程序在 0.155760 秒内执行完毕
最佳答案
你在那里滥用 NumPy 。尤其是带有数组元素的 +=
似乎几乎占据了所有时间。
这就是我的做法,大约需要 0.5 秒:
from itertools import repeat
for N in range(9):
print(sum(repeat(10**-N, 10**N)))
输出(Try it online!):
1
0.9999999999999999
1.0000000000000007
1.0000000000000007
0.9999999999999062
0.9999999999980838
1.000000000007918
0.99999999975017
1.0000000022898672
正如 @AndrasDeak 评论的那样,由于多项优化,速度很快。我们也尝试更少的优化。
首先,只摆脱 NumPy,使用简单的 Python float 。顺便说一句,你的原始内容也花了我大约 230 秒。这大约只需要 29 秒:
for N in range(9):
total = 0
for _ in range(10**N):
total += (10**-N)
print(total)
接下来,不要一遍又一遍地重新计算附加值。大约需要 11 秒:
for N in range(9):
total = 0
add = 10**-N
for _ in range(10**N):
total += add
print(total)
接下来,摆脱无缘无故产生大量 int 对象的 range
。让我们使用 itertools.repeat,它是我所知道的最快的迭代器。大约需要 9 秒:
from itertools import repeat
for N in range(9):
total = 0
add = 10**-N
for _ in repeat(None, 10**N):
total += add
print(total)
或者,大约相同的速度:
from itertools import repeat
for N in range(9):
total = 0
for add in repeat(10**-N, 10**N):
total += add
print(total)
只需将其放入函数中即可受益于局部变量比全局变量更快。大约需要 3.3 秒:
from itertools import repeat
def run():
for N in range(9):
total = 0
for add in repeat(10**-N, 10**N):
total += add
print(total)
run()
这可能是我用普通干净的 for
循环所能做到的最快的速度(循环展开会有所帮助,但是呃...)。
我的 sum(repeat(...))
版本让 C 代码完成所有工作(sum
甚至 optimizes summation of floats ),使其成为还是快了很多。
关于python - 长 For 循环执行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71096422/