每运行10,000次,我们得到这些:
Simple list lookup: 0.3219145839975681
Binary trick: 0.37199034500008565
使列表查找成为更快的解决方案。但是,运行100,000次,我们得到了以下信息:
Simple list lookup: 3.265285526002117
Binary trick: 0.3752144949976355
然后,二元技巧显然是优越的(正如我所期望的那样)。
为什么我会得到不同的结果?
代码如下:
from math import pow
POWERS = [pow(2, x) for x in range(0, 31)]
def list_lookup(x):
"""Is a power of two, via a simple list lookup."""
return x in POWERS
def binary_trick(x):
"""Is a power of two, via a simple binary trick from stackoverflow."""
return x > 0 and (int(x) & (int(x) - 1)) == 0
def test(func):
"""Tests the function "func" with lots of values."""
data = [(pow(2, x), True) for x in range(0, 31)]
data += [(pow(3, x), False) for x in range(1, 31)] # Not one.
for x, ex in data:
assert func(x) is ex, "Debug: x={} → ex={}".format(x, ex)
if __name__ == '__main__':
import timeit
print("Simple list lookup: {}".format(
timeit.timeit("test(list_lookup)",
number=100000,
globals=globals(),
setup="from __main__ import test")))
print("Binary trick: {}".format(
timeit.timeit("test(binary_trick)",
number=10000,
globals=globals(),
setup="from __main__ import test")))
答案 0 :(得分:1)
TL:DR
您有错字。您正在执行test(list_lookup)
100,000次和test(binary_trick)
10,000次。
检查一下:
times = 10000
print("Simple list lookup: {}".format(
timeit.timeit("test(list_lookup)",
number=times,
globals=globals(),
setup="from __main__ import test")))
print("Binary trick: {}".format(
timeit.timeit("test(binary_trick)",
number=times,
globals=globals(),
setup="from __main__ import test")))
输出
Simple list lookup: 0.523675318
Binary trick: 0.6955866560000001
将times
更改为100000
的输出
Simple list lookup: 5.717076507
Binary trick: 6.923508393999999
list_lookup
总是更快。罪魁祸首似乎是binary_trick
叫两次int(x)
。
通过times = 100000
和return x > 0 and (int(x) & (int(x) - 1)) == 0
进行测试
Simple list lookup: 3.343818478
Binary trick: 4.621393652
将binary_trick
更改为
x = int(x)
return x > 0 and (x & (x - 1)) == 0
使速度加快1秒:
Simple list lookup: 3.269909124
Binary trick: 3.1319104420000006
但是我们可以通过将list_lookup
设置为set_lookup
来提高速度:
POWERS = {pow(2, x) for x in range(0, 31)}
并再次测试100,000次:
Simple list lookup: 1.443394541
Binary trick: 2.9750550150000006