# python - pypy

## 为什么2*x*x比Python 3.x中的2*(x*x)快,对于整数? (3)

``````import time
start_time = time.time()
num = 0
for x in range(0, 10000000):
# num += 2 * (x * x)
num += 2 * x * x
print("--- %s seconds ---" % (time.time() - start_time))``````

``````   2 * x * x        |   2 * (x * x)
---------------------------------------
1.7717654705047607  | 2.0789272785186768
1.735931396484375   | 2.1166207790374756
1.7093875408172607  | 2.024367570877075
1.7004504203796387  | 2.047525405883789
1.6676218509674072  | 2.254328966140747
1.699510097503662   | 2.0949244499206543
1.6889283657073975  | 2.0841963291168213
1.7243537902832031  | 2.1290600299835205
1.712965488433838   | 2.1942825317382812
1.7622807025909424  | 2.1200053691864014``````

`2 * x * x`相关部分：

``````7          28 LOAD_FAST                1 (num)
30 LOAD_CONST               3 (2)
32 LOAD_FAST                2 (x)
34 BINARY_MULTIPLY
36 LOAD_FAST                2 (x)
38 BINARY_MULTIPLY
40 INPLACE_ADD
42 STORE_FAST               1 (num)
44 JUMP_ABSOLUTE           24``````

`2 * (x * x)`相关部分：

``````  7          28 LOAD_FAST                1 (num)
30 LOAD_CONST               3 (2)
32 LOAD_FAST                2 (x)
34 LOAD_FAST                2 (x)
36 BINARY_MULTIPLY                 <=== 1st multiply x*x in a temp value
38 BINARY_MULTIPLY                 <=== then multiply result with 2
40 INPLACE_ADD
42 STORE_FAST               1 (num)
44 JUMP_ABSOLUTE           24``````

``````>>> timeit("for i in range(1000): 2*i*i")
51.00784397125244
>>> timeit("for i in range(1000): 2*(i*i)")
50.48330092430115``````

`x*x`的位数大约是`2*x``x`两倍（因为log（x 2 ）= 2 log（x））。 请注意，此上下文中的“数字”不是基数为10的数字，而是30位值（在CPython的实现中将其视为单个数字）。 因此， `2`是单位数值， `x``2*x`是循环的所有迭代的单位数值，但`x*x``x >= 2**15`的两位数。 因此，对于`x >= 2**15` `2*x*x`仅需要逐个单位数的乘法，而`2*(x*x)`需要单个乘单和一个乘两位数乘法（因为`x*x`有2个30位数字）。

``````>>> timeit("a*b", "a,b = 2, 123456**2", number=100000000)
5.796971936999967
>>> timeit("a*b", "a,b = 2*123456, 123456", number=100000000)
4.3559221399999615``````

``````>>> timeit("a*b", "a,b = 2, 123456**2", number=100000000)
3.0912468433380127
>>> timeit("a*b", "a,b = 2*123456, 123456", number=100000000)
3.1120400428771973``````

（一个有趣的注意事项：如果你看一下这个来源，你会发现算法实际上有一个特殊情况用于平方数字（我们在这里做），但即使这仍然不足以克服`2*(x*x)`的事实`2*(x*x)`只需要处理更多数字。）