恐怕,在answer(2000000000,10**4)
的輸入中,你永遠不會「及時完成」。
您可以通過改善內循環,在c
變量每次不更新,並使用xrange
代替range
,這樣得到相當顯著加快:
def answer(start, length):
val=0
c=0
for i in range(length):
for j in range(length):
if j < length-i:
val^=start+c
c+=1
return val
def answer_fast(start, length):
val = 0
c = 0
for i in xrange(length):
for j in xrange(length - i):
if j < length - i:
val ^= start + c + j
c += length
return val
# print answer(10, 20000)
print answer_fast(10, 20000)
探查表明,answer_fast
約兩倍儘快:
> python -m cProfile script.py
366359392
20004 function calls in 46.696 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 46.696 46.696 script.py:1(<module>)
1 44.357 44.357 46.696 46.696 script.py:1(answer)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
20001 2.339 0.000 2.339 0.000 {range}
> python -m cProfile script.py
366359392
3 function calls in 26.274 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 26.274 26.274 script.py:1(<module>)
1 26.274 26.274 26.274 26.274 script.py:12(answer_fast)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
但是,如果你想要主要的加速(magnitute訂單),你應該考慮在Cython中重寫你的函數。
這裏是它的「cythonized」版本:
def answer(int start, int length):
cdef int val = 0, c = 0, i, j
for i in xrange(length):
for j in xrange(length - i):
if j < length - i:
val ^= start + c + j
c += length
return val
隨着與上述相同的輸入參數,它需要小於200ms insted的20+秒,這是一個100倍的加速。
> ipython
In [1]: import pyximport; pyximport.install()
Out[1]: (None, <pyximport.pyximport.PyxImporter at 0x7f3fed983150>)
In [2]: import script2
In [3]: timeit script2.answer(10, 20000)
10 loops, best of 3: 188 ms per loop
隨着你的輸入參數,它需要58ms:
In [5]: timeit script2.answer(2000000000,10**4)
10 loops, best of 3: 58.2 ms per loop
你在計算什麼? – khelwood
請參閱http://stackoverflow.com/a/39941113/4014959和http://stackoverflow.com/questions/10670379/find-xor-of-all-numbers-in-a-given-range –
@ PM2Ring第一個鏈接正是我想要的。謝謝。\ – sbrm1