通过Binet's formula,第n个斐波那契数大约是sqrt(5)*phi**n
,其中phi
是黄金口粮。您可以使用基地披对数轻松恢复索引:
from math import log, sqrt
def fibs(n):
nums = [1,1]
for i in range(n-2):
nums.append(sum(nums[-2:]))
return nums
phi = (1 + sqrt(5))/2
def fibIndex(f):
return round((log(sqrt(5)*f,phi)))
为了测试这个:
for f in fibs(20): print(fibIndex(f),f)
输出:
2 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765
当然,
def adjacentFibs(f,g):
return abs(fibIndex(f) - fibIndex(g)) == 1
这以失败- 但是对于这种边界情况显式测试特殊逻辑没有多大意义。如果你愿意,可以添加它。
在某个阶段,浮点四舍五入错误将成为一个问题。为此,您需要用整数对数算法(例如涉及二进制搜索的算法)替换math.log
。
在编辑:
我集中于如何恢复指数(而且我会信守答案,因为这是在自己的权利一个有趣的问题)的问题,但作为@LeandroCaniglia指出了他们的优秀评论,如果你想要做的只是检查两个斐波那契数是否相邻,这是过度的,因为Binet公式的另一个结果是足够大的相邻斐波那契数有一个与phi
相差很小的比率。你可以这样做:
def adjFibs(f,g):
f,g = min(f,g), max(f,g)
if g <= 34:
return adjacentFibs(f,g)
else:
return abs(g/f - phi) < 0.01
这假设他们确实是斐波那契数。基于索引的方法可以用来验证它们(计算索引,然后使用具有该索引的完整Binet公式)。
多少斐波那契数你有吗?我很好奇,因为斐波纳契是一个非常快速增长的序列 – yvs
检查分数是否在0.6到1.7之间,如果您确定数字实际上是斐波那契数列的成员。 – LutzL
使用您的方法获得10个第一个斐波纳契数。对于较大的计算最大斐波拉契数F和小数f和数phi =(1 + sqrt(5))的商F/f之间的距离(即它们的差的绝对值)/2'。如果距离'| F/f - phi |'小于0.01,那么它们是连续的,否则它们不是(如@LuzL所说,只要它们都是斐波那契)。 –