【问题标题】:Calculating nth fibonacci number using the formulae in python使用python中的公式计算第n个斐波那契数
【发布时间】:2012-08-19 16:34:59
【问题描述】:

我正在计算第 n 个斐波那契数,使用 (a) 线性方法,以及 (b) this 表达式

Python 代码:

'Different implementations for computing the n-th fibonacci number'

def lfib(n):
    'Find the n-th fibonacci number iteratively'
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

def efib(n):
    'Compute the n-th fibonacci number using the formulae'
    from math import sqrt, floor
    x = (1 + sqrt(5))/2
    return long(floor((x**n)/sqrt(5) + 0.5))


if __name__ == '__main__':
  for i in range(60,80):
    if lfib(i) != efib(i):
      print i, "lfib:", lfib(i)
      print "   efib:", efib(i)

对于 n > 71,我看到这两个函数返回不同的值。

这是因为 efib() 中涉及浮点运算吗? 如果是这样,是否建议使用matrix form 计算数字?

【问题讨论】:

    标签: python algorithm fibonacci


    【解决方案1】:

    您确实看到了舍入错误。

    矩阵形式是更准确的更快的算法。 Literateprograms.org 列出了一个很好的实现,但它也列出了以下基于卢卡斯数的算法:

    def powLF(n):
        if n == 1:     return (1, 1)
        L, F = powLF(n//2)
        L, F = (L**2 + 5*F**2) >> 1, L*F
        if n & 1:
            return ((L + 5*F)>>1, (L + F) >>1)
        else:
            return (L, F)
    
    def fib(n):
        if n & 1:
            return powLF(n)[1]
        else:
            L, F = powLF(n // 2)
            return L * F
    

    查看Lecture 3 of the MIT Open Courseware course on algorithms,了解矩阵方法的良好分析。

    上述算法和矩阵方法都具有 Θ(lg n) 复杂度,就像您使用的朴素递归平方方法一样,但没有舍入问题。卢卡斯数方法具有最低的常数成本,使其成为更快的算法(大约是矩阵方法的两倍):

    >>> timeit.timeit('fib(1000)', 'from __main__ import fibM as fib', number=10000)
    0.40711593627929688
    >>> timeit.timeit('fib(1000)', 'from __main__ import fibL as fib', number=10000)
    0.20211100578308105
    

    【讨论】:

      【解决方案2】:

      这是因为 efib() 中涉及浮点运算吗?

      是的,是的。在efib 内你有

      >>> log(x**72)/log(2)
      49.98541778140445
      

      Python floats have about 53 bits of precision 在 x86-64 硬件上运行,因此您正在接近边缘运行。

      【讨论】:

        【解决方案3】:

        我有一个非常简单的纯python代码...

        def fibonum(n):   # Give the nth fibonacci number
            x=[0,1]
            for i in range(2,n):
                x.append(x[i-2]+x[i-1])
            print(x[n-1])
        

        【讨论】:

        • 没有必要用.append在内存中建立一个列表。您可以只使用两个变量——参见 OP 中 lfib 的定义。
        猜你喜欢
        • 1970-01-01
        • 2022-12-10
        • 1970-01-01
        • 2020-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-11
        • 2013-03-31
        相关资源
        最近更新 更多