以下是获取第一个30000前缀的几个版本和计时。为了简单起见,我忽略了前两个收益率和最后一位数字。
fibby1
是刚使用str(b)[:9]
的原始方式。
fibby2
记录10除以的适当能力。
fibby3
保留a
和b
中的前9位数字,其余数字位于A
和B
。与fibby2
相比,这样可以避免用大的幂数来划分大的数字。大数字只能被加/减/比较,或乘以一个很小的数字。
fibby4
使用math.log10
由@therefromhere建议。
fibby5
使用decimal
模块。
输出:
All agree? True
fibby1: 24.835 seconds
fibby2: 0.289 seconds
fibby3: 0.201 seconds
fibby4: 2.802 seconds
fibby5: 0.216 seconds
只是为了比较,我也试过str(b % 10**9)
,即最后9个位数,而把0.506秒。哪个是慢于比我的前九位数的快速解决方案。
代码:
def fibby1():
a, b = 1, 1
while True:
yield str(b)[:9]
a, b = b, a+b
def fibby2():
a, b = 1, 1
div = 1
while True:
while True:
front = b // div
if front < 10**9:
break
div *= 10
yield str(front)
a, b = b, a+b
def fibby3():
a,b = 1,1
A,B,C = 0,0,1
while True:
yield str(b)
a, b = b, a+b
A, B = B, A+B
if B >= C:
B -= C
b += 1
if b >= 10**9:
A += a%10 * C
B += b%10 * C
a //= 10
b //= 10
C *= 10
def fibby4():
from math import log10
a, b = 1, 1
while True:
yield str(b // 10**max(0, int(log10(b) - 8)))
a, b = b, a+b
def fibby5():
from decimal import Decimal, getcontext
getcontext().prec = 7000 # enough for n = 30000
a, b = Decimal(1), Decimal(1)
while True:
yield str(b)[:9]
a, b = b, a+b
from timeit import timeit
from itertools import islice
from time import time
n = 30000
t0 = time()
list1 = list(islice(fibby1(), n))
t1 = time()
list2 = list(islice(fibby2(), n))
t2 = time()
list3 = list(islice(fibby3(), n))
t3 = time()
list4 = list(islice(fibby4(), n))
t4 = time()
list5 = list(islice(fibby5(), n))
t5 = time()
print('All agree?', list1 == list2 == list3 == list4 == list5)
print('fibby1: %6.3f seconds' % (t1 - t0))
print('fibby2: %6.3f seconds' % (t2 - t1))
print('fibby3: %6.3f seconds' % (t3 - t2))
print('fibby4: %6.3f seconds' % (t4 - t3))
print('fibby5: %6.3f seconds' % (t5 - t4))
你所说的 “更好的结果” 是什么意思?你获得了哪些结果?他们有什么错误? – ypnos
我不确定它会比将整个数字转换为字符串更高效,但您可以使用'math.log10()'来计算数字,'//'做一个整数除法来获取最重要的数字。 –
我的意思是在时间表现方面。例如,最低有效位在6秒钟内弹出10 ** 8,而MSB需要2分钟以上(单独测试)。 MSB可以成为LSB的时间匹配吗? –