我正在玩Python中的大数字,我运行了
的计算2**(1322134) - 2**(1322134)
显然需要很长时间才能计算出来。但是当我运行
的计算时DataContext = this;
它立即返回0.
如果不进行计算,Python如何自动告诉这些是相同的数字?
答案 0 :(得分:4)
缓慢的部分是打印数字,而不是计算它:
In [1]: %timeit str(2**1322134)
1 loop, best of 3: 2.28 s per loop
In [2]: %timeit 2**1322134
10000000 loops, best of 3: 24.8 ns per loop
您可以通过将结果存储在变量中来查看:
>>> x = 2**1322134
>>> y = 2**1322134
>>> x - y
0
上述代码将立即执行,因为Python不会在屏幕上打印出近400,000个数字。
答案 1 :(得分:3)
实际上我无法重现这个例子:
i = 1322134
%timeit 2 ** i - 2 ** i # 10 loops, best of 3: 24.8 ms per loop
花费(大约)两倍的时间
i = 1322134
%timeit 2 ** i # 100 loops, best of 3: 12.7 ms per loop
取。
有一个例外 - 如果你"硬编码"你的价值:
%timeit 2 ** 1322134 # 10000000 loops, best of 3: 61.5 ns per loop
%timeit 2 ** 1322134 - 2 ** 1322134 # 10000000 loops, best of 3: 61.3 ns per loop
因为Python会计算出这个"常数"当它将它转换为字节码并且只在运行时查找它(几乎是免费的)。
您始终可以通过dis.dis
:
import dis
def func1():
return 2 ** 1322134 - 2 ** 1322134
dis.dis(func1)
# 2 0 LOAD_CONST 5 (0) # just loads the constant
# 3 RETURN_VALUE
def func2():
i = 1322134
return 2 ** i - 2 ** i
dis.dis(func2)
# 2 0 LOAD_CONST 1 (1322134)
# 3 STORE_FAST 0 (i)
#
# 3 6 LOAD_CONST 2 (2)
# 9 LOAD_FAST 0 (i)
# 12 BINARY_POWER
# 13 LOAD_CONST 2 (2)
# 16 LOAD_FAST 0 (i)
# 19 BINARY_POWER
# 20 BINARY_SUBTRACT
# 21 RETURN_VALUE
所以func2
执行它应该执行的所有指定操作,而func1
只是加载并返回已经预先计算的(计算在转换时完成!)值。
如果您想知道为什么显示它需要这么长时间,我认为@Blender
s answer是正确的。如果你想显示某些内容,那么Python会将repr(obj)
打印到sys.stdout
- 所以你有一个案例,其中1个字符(0
)被转换为字符串然后打印,另一个案例在哪里需要创建,传递和打印398,002个字符。只是创建repr
非常慢:
i = 1322134
%timeit repr(2 ** i - 2 ** i) # 10 loops, best of 3: 24.7 ms per loop
%timeit repr(2 ** i) # 1 loop, best of 3: 6.34 s per loop # <--- whoops that's slow!
答案 2 :(得分:1)
CAVEAT:下面的初步解释是错误的。我把它留在这里作为自我教育和社区工作的一个例子。我通过高级编译器构建的教育和Python内部的部分知识来实现它。
----错误的答案----
表达式处理程序内置了优化。减法的表达式求值程序的工作方式如下:
1. reserve space for first operand:
2 already exists as a frequently-used small integer
temp1 = 1322134
temp2 = 2^(temp1)
2. reserve space for second operand:
2 already exists
13322134 already exists as temp1
2^(temp1) already exists as temp2
3. reserve space for the result:
temp3 = temp2 - temp2
Hey! That's a really easy operation!
The result is 0, which already exists as a frequently-used small integer.
----错误的回答----
更多实验
为了测试操作,我进行了这些调整:
代码:
>>> def pow2(i):
... for _ in range(1000):
... qqq = 2 ** i
... i += 1
...
>>> def powsub(i):
... for _ in range(1000):
... qqq = 2 ** i - 2 ** i
... i += 1
...
>>> import time
j = 987654
>>> start = time.time(); pow2(j); print time.time() - start
7.41031980515
>>> start = time.time(); powsub(j); print time.time() - start
15.060614109
我还测试了原始循环时间,用RHS 2 替换 qqq 计算。这花了不到一毫秒。
从此,我观察到了
<强>结论强>
我原来的回答是错误。 MSeifert和Blender钉了它。
我在这里留下这个答案是一个失败的反例。