Python需要更多时间来打印计算而不是执行计算

时间:2014-03-30 17:48:54

标签: python performance variables numerical-computing

我在python中编写了一个脚本,这令我感到惊讶。 基本上,它需要五个20位数字,然后将它们相乘,然后将它们提升到3000的幂。时间模块用于查找计算计算所需的时间。好吧,当我运行这个脚本时,它说需要3 * 10 ^ -7秒来计算它。 然后它生成一个文件output.txt,但脚本在大约15秒后才会结束。

import timeit
outputFile = open("output.txt", "w")
start = timeit.default_timer()
x = (87459837581209463928*23745987364728194857*27385647593847564738*10293769154925693856*12345678901234567891)**3000
stop = timeit.default_timer()
time = stop-start
print "Time taken for the calculation was {} seconds".format(time)
outputFile.writelines(str(x))
outputFile.close()
y = raw_input("Press enter to exit.")

这是否意味着打印280kb文件实际上需要花费更长的时间而不是执行计算?(我觉得不太可能。)

如果不是这样,那么python是否在调用变量x时执行计算?它是在每次计算变量时执行计算,还是将实际值存储在变量?

我刚刚编写了另一个脚本,它确认将结果写入.txt文件需要python 0.03秒。那么,为什么python稍后会执行计算?

3 个答案:

答案 0 :(得分:7)

这不是计算问题,也不是写入文件:通过将结果从其内部二进制表示转换为基数10表示来消耗大量时间。这需要时间二进制的位数,这里你有很多位。

如果用以下代码替换输出行:

outputFile.writelines(hex(x))

你会发现它的运行速度非常快。转换为十六进制表示只需要时间线性的位数。

如果您确实需要以基数10表示输出巨整数,请查看使用decimal模块。它在与基数10相关的表示中进行内部计算,然后转换为十进制字符串需要十进制数字的线性时间。但是,您需要提前将小数上下文的精度设置为“足够大”的值,以避免将低位数丢失为舍入。

答案 1 :(得分:1)

转换为字符串需要很长时间:

In [68]: %time x = (87459837581209463928*23745987364728194857*27385647593847564738*10293769154925693856*12345678901234567891)**3000
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.00 s

In [69]: %time xs = str(x)
CPU times: user 1.98 s, sys: 0.00 s, total: 1.98 s
Wall time: 1.98 s

In [71]: %time print xs
CPU times: user 0.01 s, sys: 0.00 s, total: 0.01 s
Wall time: 0.04 s

但数字有数十万个数字应该不足为奇。

修改

与其他答案相反,写入文件并不需要那么多时间:

In [72]: %time with open('tmp.file', 'w') as f: f.write(xs)
CPU times: user 0.00 s, sys: 0.01 s, total: 0.01 s
Wall time: 0.00 s

答案 2 :(得分:1)

除了其他答案,请使用outputFile.write(str(x))代替writelines。 writelines意味着与一系列字符串一起使用。在您的情况下,它迭代字符串并单独写入每个字符。在一个简单的测试中,writelines慢了3.7倍:

>>> timeit("f.writelines(str(s))", setup="f=open('tmp.txt','w');s=range(1000)", number=10000)
4.935087700632465
>>> timeit("f.write(str(s))", setup="f=open('tmp.txt','w');s=range(1000)", number=10000)
1.3468097837871085