如何编写斐波那契数列?

我最初编写的程序错误。 代替的范围之间返回斐波那契数的(即startNumber 1,endNumber 20应该=只有1 20之间的那些数),我已经写了该程序的范围之间显示所有斐波那契数(即startNumber 1,endNumber 20显示器=前20个斐波纳契数字)。 我以为我有一个确定的代码。 我也不明白为什么会发生这种情况。

startNumber = int(raw_input("Enter the start number here "))
endNumber = int(raw_input("Enter the end number here "))

def fib(n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)

print map(fib, range(startNumber, endNumber))

有人在我的第二部分(其被关闭,作为一个重复的 - https://stackoverflow.com/questions/504193/how-to-write-the-fibonacci-sequence-in-python-part-ii)指出,我需要通过使用while循环的生成器传递startNumber和endNumber。 有人可以请我指出如何做到这一点? 欢迎任何帮助。


我是一个学习程序员,我遇到了一些混乱。 我被要求编写一个程序,用户通过输入的起始号码和结束号码(即startNumber = 20 endNumber = 100,它将只显示该范围之间的数字)来计算并显示斐波那契序列。 诀窍在于包含性地使用它(我不知道如何在Python中做什么 - 我假设这意味着使用包含范围?)。

到目前为止,我没有真正的编码,而是:

  • 将Fib序列公式写成无穷大
  • 仅从Fib序列中将startNumber显示为endNumber。
  • 我不知道从哪里开始,我正在询问有关如何编写此内容的想法或见解。 我也试图写出Fib序列论坛,但我也迷失了。


    斐波那契数列有很多关于wikipedia和wolfram的信息。 比你可能需要的要多得多。 无论如何,学习如何使用这些资源来找到(如果可能,尽快)你需要什么是一件好事。

    将Fib序列公式写成无穷大

    在数学中,它是以递归形式给出的:

    在编程中, 无限不存在。 您可以使用递归表单直接用您的语言翻译数学表单,例如在Python中它会变成:

    def F(n):
        if n == 0: return 0
        elif n == 1: return 1
        else: return F(n-1)+F(n-2)
    

    用你最喜欢的语言来尝试一下,看看这个表格需要很多时间,因为n越来越大。 事实上,这是O(2n)。

    继续与我联系的网站,并会看到这个(在wolfram上):

    这个在Python中非常容易实现,计算速度非常快,

    from math import sqrt
    def F(n):
        return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))
    

    另一种方式是遵循定义(来自维基百科):

    该序列的第一个数字是0,第二个数字是1,并且每个后续数字等于该序列本身的前两个数字的总和,产生序列0,1,1,2,3,5,8等等

    如果你的语言支持迭代器,你可以这样做:

    def F():
        a,b = 0,1
        while True:
            yield a
            a, b = b, a + b
    

    仅从Fib序列中将startNumber显示为endNumber。

    一旦你知道如何生成斐波纳契数字,你只需要循环数字,并检查他们是否验证给定的条件。

    现在假设你写了af(n)返回斐波那契数列的第n项(如sqrt(5))

    在大多数语言中,您可以执行以下操作:

    def SubFib(startNumber, endNumber):
        n = 0
        cur = f(n)
        while cur <= endNumber:
            if startNumber <= cur:
                print cur
            n += 1
            cur = f(n)
    

    在python中,我会使用迭代器形式并去:

    def SubFib(startNumber, endNumber):
        for cur in F():
            if cur > endNumber: return
            if cur >= startNumber:
                yield cur
    
    for i in SubFib(10, 200):
        print i
    

    我的提示是要学会阅读你需要的东西。 欧拉项目(谷歌为它)将训练你这样做:P祝你好运,玩得开心!


    Fibonacci序列的高效Pythonic生成器

    我在试图获得这个序列的最短Pythonic代时发现了这个问题(后来认识到我在Python Enhancement Proposal中看到过类似的代码),并且我没有注意到有人提出了我的具体解决方案(尽管最佳答案靠近,但仍然不太优雅),所以在这里,有了描述第一次迭代的评论,因为我认为这可能有助于读者理解:

    def fib():
        a, b = 0, 1
        while True:            # First iteration:
            yield a            # yield 0 to start with and then
            a, b = b, a + b    # a will now be 1, and b will also be 1, (0 + 1)
    

    和用法:

    for index, fibonacci_number in zip(range(10), fib()):
         print('{i:3}: {f:3}'.format(i=index, f=fibonacci_number))
    

    打印:

      0:   0
      1:   1
      2:   1
      3:   2
      4:   3
      5:   5
      6:   8
      7:  13
      8:  21
      9:  34
     10:  55
    

    (出于归因的原因,我最近注意到模块的Python文档中有类似的实现,即使使用变量ab ,我现在回想起在写这个答案之前已经看到了这些变量,但我认为这个答案表明了更好地使用该语言。)

    递归定义的实现

    整数序列的在线百科全书将Fibonacci序列递归地定义为

    当F(0)= 0且F(1)= 1时,F(n)= F(n-1)+ F(n-2)

    在Python中递归地简洁地定义它可以按照如下方式完成:

    def rec_fib(n):
        '''inefficient recursive function as defined, returns Fibonacci number'''
        if n > 1:
            return rec_fib(n-1) + rec_fib(n-2)
        return n
    

    但数学定义的确切表示对于远远大于30的数字是非常低效的,因为计算的每个数字也必须为其下面的每个数字计算。 您可以通过使用以下内容来演示其速度有多慢:

    for i in range(40):
        print(i, rec_fib(i))
    

    记忆递归提高效率

    可以通过记忆来提高速度(本示例利用了每次调用函数时默认关键字参数都是同一个对象这一事实,但正因为如此,通常不会使用可变默认参数):

    def mem_fib(n, _cache={}):
        '''efficiently memoized recursive function, returns a Fibonacci number'''
        if n in _cache:
            return _cache[n]
        elif n > 1:
            return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
        return n
    

    你会发现memoized版本要快得多,并且在你甚至想起来喝咖啡之前,它会很快超过你的最大递归深度。 你可以通过这样做看到它在视觉上有多快:

    for i in range(40):
        print(i, mem_fib(i))
    

    (看起来我们可以做下面的事情,但实际上并没有让我们利用缓存,因为它在调用setdefault之前调用它自己。)

    def mem_fib(n, _cache={}):
        '''don't do this'''
        if n > 1:  
            return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
        return n
    

    递归定义的生成器:

    正如我一直在学习Haskell,我在Haskell中遇到了这个实现:

    fib@(0:tfib) = 0:1: zipWith (+) fib tfib
    

    我认为我现在可以在Python中最接近这一点的是:

    from itertools import tee
    
    def fib():
        yield 0
        yield 1
        # tee required, else with two fib()'s algorithm becomes quadratic
        f, tf = tee(fib()) 
        next(tf)
        for a, b in zip(f, tf):
            yield a + b
    

    这表明它:

    [f for _, f in zip(range(999), fib())]
    

    尽管如此,它只能达到递归限制。 通常情况下,1000,而Haskell版本可以达到百万分之几,尽管它使用笔记本电脑的全部8 GB内存来完成此操作:

    > length $ take 100000000 fib 
    100000000
    

    下面的Python代码显示了斐波那契数列背后的想法:

    def fib(n):
       if n == 1:
          return 1
       elif n == 0:   
          return 0            
       else:                      
          return fib(n-1) + fib(n-2)         
    

    这意味着fib是一种可以做三件事情之一的功能。 它将fib(1)== 1,fib(0)== 0和fib(n)定义为:

    fib(n-1)+ fib(n-2)

    其中n是一个任意整数。 这意味着fib(2)例如展开为以下算术:

    fib(2) = fib(1) + fib(0)
    fib(1) = 1
    fib(0) = 0
    # Therefore by substitution:
    fib(2) = 1 + 0
    fib(2) = 1
    

    我们可以用下面的算术计算fib(3):

    fib(3) = fib(2) + fib(1)
    fib(2) = fib(1) + fib(0)
    fib(2) = 1
    fib(1) = 1
    fib(0) = 0
    # Therefore by substitution:
    fib(3) = 1 + 1 + 0
    

    这里要实现的重要一点是,如果不计算fib(2),通过了解fib(1)和fib(0)的定义来计算fib 3,就不能计算fib 3。 有一个像斐波那契函数一样的函数调用叫做递归,它是编程中的一个重要主题。

    这听起来像一个家庭作业,所以我不打算为你做开始/结束部分。 Python虽然是一种非常具有表现力的语言,所以如果你理解数学,这应该是有意义的,并且希望能够教你关于递归。 祝你好运!

    编辑:我的代码的一个潜在的批评是,它没有使用超级方便的Python函数yield,这使得fib(n)函数缩短了很多。 我的例子虽然更通用一些,因为Python之外的很多语言实际上都没有收益。

    链接地址: http://www.djcxy.com/p/39907.html

    上一篇: How to write the Fibonacci Sequence?

    下一篇: Asymptotic analysis "o" to "O" conversion