如何写斐波那契数列?


140

我最初对程序进行了错误编码。我没有为程序返回范围内的斐波那契数(即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序列论坛,但我也对此一无所知。

Answers:


257

维基百科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(2 n)。

继续在我链接到您的网站上,将看到此信息(在Wolfram上):

斐波那契方程

这是很容易实现的,并且非常非常快速地用Python计算:

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

另一种方法是遵循定义(来自Wikipedia):

序列的第一个数字为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

我的提示是学习阅读所需内容。欧拉计画(google for Euler)将会训练您这样做:P祝您好运,玩得开心!


1
您需要使用while循环,而不是map。尝试自己弄清楚它,如果不能完成,请返回代码。我并不懒惰(代码比此注释短)。我正在为您做这件事,请尝试使用“ while”提示;)如果您对此有
疑问

我回来了,哈哈。我摆脱了map(range)函数,仅使用range(startNumber,endNumber)函数。现在,我的问题是在哪里使用while语句。我尝试在该函数的开头,但是当然有一个错误的提示。我应该放在哪里?Thx
SD。

手工尝试做一个程序输入输出示例(范围很短)。然后尝试找出程序错误的地方。尝试在代码中转换“手动方法”。这是运动,要学习。我可以放下两行代码,但我认为您不会从中学习到任何东西。
Andrea Ambu

1
我们应该使用int(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))),有什么想法吗?@AndreaAmbu
领主63。j

3
@ lord63.j,仅当您知道该公式在n高于70 时开始偏离实际值并在600略高于600 OverflowError 时爆炸时才应使用该公式。n其他方法可以处理n1000或更大的值而不会精度上升或下降。
cdlane

66

斐波那契数列的高效Python生成器

我在尝试获得该序列的最短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,我现在记得在编写此答案之前就已经看到过。但是我认为该答案展示了该语言的更好用法。)

递归定义的实现

整数序列的在线百科全书递归定义斐波那契序列

F(n)= F(n-1)+ F(n-2),其中F(0)= 0和F(1)= 1

可以在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

您会发现记住的版本要快得多,并且在您甚至可以考虑起床喝咖啡之前,它将很快超过最大递归深度。通过执行以下操作,您可以看到视觉速度:

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版本可以达到1亿,尽管它使用了笔记本电脑的全部8 GB内存:

> length $ take 100000000 fib 
100000000

消耗迭代器以获得第n个斐波那契数

评论者问:

对基于迭代器的Fib()函数的问题:如果要获取第n个,例如第10个fib号,该怎么办?

itertools文档提供了以下方法:

from itertools import islice

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

现在:

>>> nth(fib(), 10)
55

关于最后一个“不做这个”选项,我不明白为什么它会在setdefault之前调用自己。如果n是有效键,setdefault是否不应该返回值?Doc说:“如果key在字典中,则返回其值。否则,插入具有默认值的key并返回default。默认默认为None。” 我想念什么?
binithb

@binithb在setdefault调用之前先 对调用内的表达式求setdefault值。
亚伦·霍尔

23

为什么不简单地执行以下操作?

x = [1,1]
for i in range(2, 10):  
    x.append(x[-1] + x[-2]) 
print(', '.join(str(y) for y in x))

21

以下Python代码显示了Fibonacci序列背后的思想:

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(3),而fib(2)是通过了解fib(1)和fib(0)的定义来计算的。具有像fibonacci函数一样的函数调用本身称为递归,这是编程中的重要主题。

这听起来像是一项家庭作业,所以我不会为您做开始/结束部分。但是,Python是一种出色的表达语言,因此,如果您了解数学,这应该是有道理的,并有望教您有关递归的知识。祝好运!

编辑:对我的代码的一种潜在批评是它没有使用超级方便的Python函数yield,这使fib(n)函数更短了。不过,我的示例更加通用一些,因为Python之外的许多语言实际上没有收益。


这不是作业问题,但哇,谢谢您的回答!我了解我需要做的事情,但是开始并实施正是我现在所坚持的(特别是实现用户输入值)。您能对此提供一些见解吗?我一直收到<function fib at 0x0141FAF0>错误。
SD。

我了解您正在努力实施可能超出您当前能力的程序。让我编写更多代码对您无济于事。您应该尝试修改我的代码,直到它起作用为止,并阅读更多Python教程。空格可能是个问题,但我不知道该错误。
詹姆斯·汤普森

我明白。还有其他想法让您认为我可能会失踪吗?我了解您是否能帮上忙。多谢您的宝贵时间。
SD。

您的<function fib at 0x0141FAF0>错误可能是由于说“ fib”(指函数本身)而不是“ fib()”(将调用函数)引起的。祝你好运。
科伊夫

8
请记住,这种计算斐波纳契数的幼稚递归方法可以真正快速地进入堆栈溢出(而不是站点)。出于实际目的,迭代生成或使用某种类型的备注或其他内容。
David Thornley,2009年

12

时间复杂度:

缓存功能通过消除斐波那契数列的递归树中的重复项,减少了从O(2 ^ n)O(n)的斐波那契数列的正常计算方式:

在此处输入图片说明

代码:

import sys

table = [0]*1000

def FastFib(n):
    if n<=1:
        return n
    else:
        if(table[n-1]==0):
            table[n-1] = FastFib(n-1)
        if(table[n-2]==0):
            table[n-2] = FastFib(n-2)
        table[n] = table[n-1] + table[n-2]
        return table[n]

def main():
    print('Enter a number : ')
    num = int(sys.stdin.readline())
    print(FastFib(num))

if __name__=='__main__':
    main()

9

使用O(log n)基本算术运算,这非常有效。

def fib(n):
    return pow(2 << n, n + 1, (4 << 2*n) - (2 << n) - 1) % (2 << n)

这使用O(1)基本算术运算,但是中间结果的大小很大,因此根本没有效率。

def fib(n):
    return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)

该函数使用平方求幂计算多项式环Z [X] /(X ^ 2-X-1)中的X ^ n。该计算的结果是多项式Fib(n)X + Fib(n-1),从中可以读取第n个斐波那契数。

同样,这使用O(log n)算术运算并且非常有效。

def mul(a, b):
        return a[0]*b[1]+a[1]*b[0]+a[0]*b[0], a[0]*b[0]+a[1]*b[1]

def fib(n):
        x, r = (1, 0), (0, 1)
        while n:
                if n & 1: r = mul(r, x)
                x = mul(x, x)
                n >>= 1
        return r[0]

1
第一种和第三种技术是好的。第二种技术是关闭1;它实际上需要n -= 1正确工作,并且也无法使用n = 0。无论如何,如果添加了很多上下文来解释它们是如何工作的,尤其是第一种技术,那将对我有很大帮助。我在paulhankin.github.io/Fibonacci
Acumenus'December

6

用于打印斐波那契序列的规范Python代码:

a,b=1,1
while True:
  print a,
  a,b=b,a+b       # Could also use b=a+b;a=b-a

对于“打印第一个大于1000位数长的斐波那契数”的问题:

a,b=1,1
i=1
while len(str(a))<=1000:
  i=i+1
  a,b=b,a+b

print i,len(str(a)),a

4

我们知道

在此处输入图片说明

那个矩阵的n次方可以给我们:

在此处输入图片说明

因此,我们可以实现一个函数,将矩阵的幂简单地计算为第n -1个幂。

正如我们所知道的幂a ^ n等于

在此处输入图片说明

所以最后,斐波那契函数将是O(n)...如果不是因为我们也知道这一事实x^n * x^n = x^2n以及对x^n可以用复杂度O(log n )

这是我使用快速编程语言的斐波那契实现:

struct Mat {
    var m00: Int
    var m01: Int
    var m10: Int
    var m11: Int
}

func pow(m: Mat, n: Int) -> Mat {
    guard n > 1 else { return m }
    let temp = pow(m: m, n: n/2)

    var result = matMultiply(a: temp, b: temp)
    if n%2 != 0 {
        result = matMultiply(a: result, b: Mat(m00: 1, m01: 1, m10: 1, m11: 0))
    }
    return result
}

func matMultiply(a: Mat, b: Mat) -> Mat {
    let m00 = a.m00 * b.m00 + a.m01 * b.m10
    let m01 = a.m00 * b.m01 + a.m01 * b.m11
    let m10 = a.m10 * b.m00 + a.m11 * b.m10
    let m11 = a.m10 * b.m01 + a.m11 * b.m11

    return Mat(m00: m00, m01: m01, m10: m10, m11: m11)
}

func fibonacciFast(n: Int) -> Int {

    guard n > 0 else { return 0 }
    let m = Mat(m00: 1, m01: 1, m10: 1, m11: 0)

    return pow(m: m, n: n-1).m00
}

这具有复杂度O(log n)。我们计算指数为n-1的Q的幂,然后取元素m00(即Fn + 1),即在幂指数n-1处恰好是我们想要的第n个斐波那契数。

一旦有了快速斐波那契功能,就可以从开始编号和结束编号进行迭代,以获得您感兴趣的斐波那契序列的一部分。

let sequence = (start...end).map(fibonacciFast)

当然,首先要对开始和结束进行一些检查,以确保它们可以形成有效范围。

我知道这个问题已经8岁了,但是无论如何我回答都很有趣。:)


3

斐波那契序列是:1, 1, 2, 3, 5, 8, ...

也就是说f(1) = 1f(2) = 1f(3) = 2...f(n) = f(n-1) + f(n-2)

我最喜欢的实现(与其他实现相比,最简单但实现了轻量级的实现)是:

def fibonacci(n):
    a, b = 0, 1
    for _ in range(1, n):
        a, b = b, a + b
    return b

测试

>>> [fibonacci(i) for i in range(1, 10)]
[1, 1, 2, 3, 5, 8, 13, 21, 34]

定时

>>> %%time
>>> fibonacci(100**3)
CPU times: user 9.65 s, sys: 9.44 ms, total: 9.66 s
Wall time: 9.66 s

编辑: 此实现的示例可视化


3

使用递归:

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)
x=input('which fibonnaci do you want?')
print fib(x)

2

另一种方法是:

a,n=[0,1],10
map(lambda i: reduce(lambda x,y: a.append(x+y),a[-2:]),range(n-2))

将列表分配给“ a”,将整数分配给“ n” Map和reduce是python中三个最强大的函数中的2个。这里的map仅用于迭代“ n-2”次。a [-2:]将获取数组的最后两个元素。a.append(x + y)将添加最后两个元素并将其追加到数组


1

这些看起来都比他们需要的复杂。我的代码非常简单快捷:

def fibonacci(x):

    List = []
    f = 1
    List.append(f)
    List.append(f) #because the fibonacci sequence has two 1's at first
    while f<=x:
        f = List[-1] + List[-2]   #says that f = the sum of the last two f's in the series
        List.append(f)
    else:
        List.remove(List[-1])  #because the code lists the fibonacci number one past x. Not necessary, but defines the code better
        for i in range(0, len(List)):
        print List[i]  #prints it in series form instead of list form. Also not necessary

2
动态编程FTW!fibonacci(100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)几乎立即响应
Hans

6
我莫名其妙地对此表示怀疑。
拉纳鲁

如何以[0,1](即List.append(0); List.append(1))开头列表,以避免在else后面执行remove命令?...,斐波那契数应该更好地索引,因为fibonacci(10)返回的斐波那契数小于10,而不是第10个数。
SeF

1

OK ..在厌倦了引用所有冗长的答案之后,现在可以找到以下排序和简单易用的方法来在python中实现Fibonacci。您可以通过获取参数或获取用户输入来以所需的方式对其进行增强……或将限制从10000开始更改。根据需要……

def fibonacci():
    start = 0 
    i = 1 
    lt = []
    lt.append(start)
    while start < 10000:
        start += i
        lt.append(start)
        i = sum(lt[-2:])
        lt.append(i)
    print "The Fibonaccii series: ", lt

这种方法也很好。在下面找到运行分析

In [10]: %timeit fibonacci
10000000 loops, best of 3: 26.3 ns per loop

1

这是对Mathew henry答案的改进:

def fib(n):
    a = 0
    b = 1
    for i in range(1,n+1):
            c = a + b
            print b
            a = b
            b = c

该代码应打印b而不是打印c

输出:1,1,2,3,5 ....


1

使用for循环并仅打印结果

def fib(n:'upto n number')->int:
    if n==0:
        return 0
    elif n==1:
        return 1
    a=0
    b=1
    for i in range(0,n-1):
        b=a+b
        a=b-a
    return b

结果

>>>fib(50)
12586269025
>>>>
>>> fib(100)
354224848179261915075
>>> 

打印list包含所有数字的

def fib(n:'upto n number')->int:
    l=[0,1]
    if n==0:
        return l[0]
    elif n==1:
        return l
    a=0
    b=1
    for i in range(0,n-1):
        b=a+b
        a=b-a
        l.append(b)
    return l

结果

>>> fib(10)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

1
import time
start_time = time.time()



#recursive solution
def fib(x, y, upperLimit):
    return [x] + fib(y, (x+y), upperLimit) if x < upperLimit else [x]

#To test :

print(fib(0,1,40000000000000))
print("run time: " + str(time.time() - start_time))

结果

[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368 ,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,49526150 ,12586269025、20365011074、32951280099、53316291173、86267571272、139583862445、225851433717、365435296162、591286729879、956722026041、1548008755920、2504730781961、4052739537881、6557470319842、10610209857723、17167680177565、27945890035288

运行: 0.04298138618469238


1

有一个非常简单的方法可以实现这一目标!

您可以使用http://www.learnpython.org/在线免费运行此代码

# Set the variable brian on line 3!

def fib(n):
"""This is documentation string for function. It'll be available by fib.__doc__()
Return a list containing the Fibonacci series up to n."""
result = []
a = 0
b = 1
while a < n:
    result.append(a)  # 0 1 1 2 3 5  8  (13) break
    tmp_var = b       # 1 1 2 3 5 8  13
    b = a + b         # 1 2 3 5 8 13 21
    a = tmp_var       # 1 1 2 3 5 8  13
    # print(a)
return result

print(fib(10))
# result should be this: [0, 1, 1, 2, 3, 5, 8]

一种简单的方法,仅需使用迭代器即可实现Fibonacci系列,而无需任何复杂的递归数据结构!
xgqfrms

1

可以通过以下方式完成。

n = 0

数字= [0]

对于我在范围(0,11)中:
    打印n
    数字。追加(n)
    上一个=数字[-2]
    如果n == 0:
        n = 1
    其他:
        n = n +前

1

只是为了好玩,在Python 3.8+中,您可以在列表推导中使用赋值表达式(又名walrus运算符),例如:

>>> a, b = 0, 1
>>> [a, b] + [b := a + (a := b) for _ in range(8)]  # first 10 Fibonacci numbers
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

赋值表达式使您可以为变量赋值并在同一表达式中返回它。因此,表达

b := a + (a := b)

相当于执行

a, b = b, a + b

并返回的值b


0

在学习Python时使用的教程中,有15分钟的时间,它要求读者编写一个程序,该程序将根据3个输入数字(第一个斐波纳契数字,第二个数字和停止该序列的数字)来计算斐波纳契数列。本教程只介绍了if / thens变量,并且一直循环到这一点。尚无功能。我想出了以下代码:

sum = 0
endingnumber = 1                

print "\n.:Fibonacci sequence:.\n"

firstnumber = input("Enter the first number: ")
secondnumber = input("Enter the second number: ")
endingnumber = input("Enter the number to stop at: ")

if secondnumber < firstnumber:

    print "\nSecond number must be bigger than the first number!!!\n"

else:

while sum <= endingnumber:

    print firstnumber

    if secondnumber > endingnumber:

        break

    else:

        print secondnumber
        sum = firstnumber + secondnumber
        firstnumber = sum
        secondnumber = secondnumber + sum

如您所见,它的效率很低,但确实可以。


0
def fib():
    a,b = 1,1
    num=eval(input("Please input what Fib number you want to be calculated: "))
    num_int=int(num-2)
    for i in range (num_int):
        a,b=b,a+b
    print(b)

3
eval(input())这里不需要;我认为int(input())在这种情况下更好。
GingerPlusPlus 2014年

0

只是通过http://projecteuler.net/problem=2这就是我的看法

# Even Fibonacci numbers
# Problem 2

def get_fibonacci(size):
    numbers = [1,2]
    while size > len(numbers):
        next_fibonacci = numbers[-1]+numbers[-2]
        numbers.append(next_fibonacci)

    print numbers

get_fibonacci(20)

0
def fib(x, y, n):
    if n < 1: 
        return x, y, n
    else: 
        return fib(y, x + y, n - 1)

print fib(0, 1, 4)
(3, 5, 0)

#
def fib(x, y, n):
    if n > 1:
        for item in fib(y, x + y, n - 1):
            yield item
    yield x, y, n

f = fib(0, 1, 12)
f.next()
(89, 144, 1)
f.next()[0]
55

0

也许这会有所帮助

def fibo(n):
    result = []
    a, b = 0, 1
    while b < n:
            result.append(b)
            a, b = b, b + a
    return result

0

基于经典的斐波那契数列,仅出于单线考虑

如果只需要索引号,则可以使用reduce(即使reduce不是最适合该索引,这也是一个不错的练习)

def fibonacci(index):
    return reduce(lambda r,v: r.append(r[-1]+r[-2]) or (r.pop(0) and 0) or r , xrange(index), [0, 1])[1]

并获得完整的数组,只需删除or(r.pop(0)和0)

reduce(lambda r,v: r.append(r[-1]+r[-2]) or r , xrange(last_index), [0, 1])

0

这个怎么样?我猜它不如其他建议那么花哨,因为它要求对先前结果进行初始说明才能产生预期的输出,但是我觉得这是一个非常易读的选项,即它所做的就是将结果和先前的结果提供给递归。

#count the number of recursions
num_rec = 0

def fibonacci(num, prev, num_rec, cycles):

    num_rec = num_rec + 1

    if num == 0 and prev == 0:
        result  = 0;
        num = 1;
    else:
        result = num + prev

    print(result)

    if num_rec == cycles:
        print("done")
    else:
        fibonacci(result, num, num_rec, cycles)

#Run the fibonacci function 10 times
fibonacci(0, 0, num_rec, 10)

这是输出:

0
1
1
2
3
5
8
13
21
34
done

0

基本上是从Ruby翻译的:

def fib(n):
    a = 0
    b = 1
    for i in range(1,n+1):
            c = a + b
            print c
            a = b
            b = c

...


0
def fib(lowerbound, upperbound):
    x = 0
    y = 1
    while x <= upperbound:
        if (x >= lowerbound):
            yield x
        x, y = y, x + y

startNumber = 10
endNumber = 100
for fib_sequence in fib(startNumber, endNumber):
    print "And the next number is... %d!" % fib_sequence

0

关于斐波那契数列记忆的工作原理的更详细说明。

# Fibonacci sequence Memoization

fib_cache = {0:0, 1:1}

def fibonacci(n):
    if n < 0:
        return -1
    if fib_cache.has_key(n):
        print "Fibonacci sequence for %d = %d cached" % (n, fib_cache[n])
        return fib_cache[n]
    else:
        fib_cache[n] = fibonacci(n - 1) + fibonacci(n - 2)
    return fib_cache[n]

if __name__ == "__main__":
    print fibonacci(6)
    print fib_cache
    # fibonacci(7) reuses fibonacci(6) and fibonacci(5)
    print fibonacci(7)
    print fib_cache

0

我试图避免使用递归函数来解决此问题,所以我采取了迭代方法。我原本是在做一个记忆化的递归函数,但一直没有达到最大递归深度。我也有严格的内存目标,因此您会看到我在循环过程中将数组保持尽可能小,而在任何时候都只能在数组中保留2-3个值。

def fib(n):
    fibs = [1, 1] # my starting array
    for f in range(2, n):
        fibs.append(fibs[-1] + fibs[-2]) # appending the new fib number
        del fibs[0] # removing the oldest number
    return fibs[-1] # returning the newest fib

print(fib(6000000))

在我的机器上,获得第600万个斐波那契数仅需282秒,而600k斐波那契数仅需2.8秒。我无法通过递归函数获得如此大的斐波那契数,即使是被记忆的数字也是如此。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.