Python:斐波那契数列

9

我只是想通过编写一些基本函数来提高我的编程技能。

我想用斐波那契数列值填充一个列表,但我认为我的代码给出了所有数字的总和并打印该值。

numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

print numberlist

fibonaccinumbers = []

for n in numberlist:
    def fib(n):
        a, b = 0, 1
        for i in range(n):
            a, b = b, a + b
        return a
    a = fib(n)
    fibonaccinumbers.append(a)


print a

我哪里做错了?


4
任何以“我一直在努力提高我的技能”开头的问题都应该得到点赞和立即关注。 - salezica
“a,b = b,a+b”:这是一种令人困惑的赋值方式!我知道它是有效的,但我无法不认为它不应该被允许。 - lucasg
4
在Python中,a, b = b, a + b是完全可以的。 - jfs
2
@georgesl,一旦你习惯了它,你会想知道为什么其他语言不能像多个返回值一样干净。 - Jason Sperske
1
@DaBx 我说的完全是实话!提高自己是程序员最崇高的目标。 - salezica
显示剩余3条评论
11个回答

12
print a

好的,你打印最终值。


此外,关于您的代码还有一些评论:
numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

您不需要在那里初始化 i,因为for循环会为您完成。此外,您可以通过执行以下操作简化整个块:

numberlist = list(range(20))

鉴于您实际上不需要将其作为列表,因此根本不需要构建它,但是稍后可以运行for n in range(20)

然后,您正在循环重复定义您的fib函数。您应该在其外部定义并仅重复使用它。

此外,当您知道要创建多个斐波那契数的列表时,最好只存储计算得到的所有数字之间的所有数字。这样,您不必一遍又一遍地执行相同的操作。您还可以使用生成器函数使所有这些变得更加容易:

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

fibonaccinumbers = []
fib = fibGenerator()
for n in range(20):
    fibonaccinumbers.append(next(fib))

不必手动迭代范围并在生成器上调用next,您可以使用itertools中的take-recipe轻松完成此操作:

fibonaccinumbers = take(20, fibGenerator())

关于生成器

我还不太确定生成器到底是做什么用的。

生成器是一种Python函数,可以生成一个序列的返回值。这些值会在你请求它们时惰性地生成。你只需要用 yield 代替 return 就可以创建生成器了。一个 yield 语句将“返回”一个值并且暂停生成器。下一次你请求一个值时,生成器会从上次离开的地方继续执行。

使用生成器可以让你创建无限序列。正如上面的 fibGenerator 函数定义中所看到的,其中有一个无限循环,并带有一个 yield 语句。当生成器停止时,即使循环没有结束,它也不会挂起。

这里是一个简单的自我说明性例子:

>>> def example():
    print('begin')
    i = 0
    while True:
        print('Calculating next value')
        yield i
        i += 1

>>> g = example()
>>> next(g)
begin
Calculating next value
0
>>> next(g)
Calculating next value
1
>>> next(g)
Calculating next value
2
>>> next(g)
Calculating next value
3
>>> next(g)
Calculating next value
4
< p > next 函数是内置函数,用于从 可迭代对象 中请求下一个值。可迭代对象是指任何可以被迭代的对象(例如,for x in iterable: ...),而任何生成器也都是可迭代对象。


@uʍopǝpısdn 哈哈,第一! :P ^^ - poke
我见过的yield语句最好的解释。它很适合我的斐波那契数列实验。谢谢! - WyomingGeezer

2

对不起,我有些傻。我打印的是斐波那契数列的最后一个计算结果 'a',而不是整个列表。

我应该打印整个列表。

真是糟糕...


1
虽然你发帖的时间有点晚,但还是很好。建议:1)将函数定义移到循环外面。2)range返回一个列表,所以你可以只说for n in range(20)而不是for n in numberlist并在开始时做所有这些工作。3)我建议你研究一下列表推导式,第二个循环可能看起来像这样:fibonaccinumbers = [fib(n) for n in range(20)] - Justin

2

我来分享一些Python爱心:

def fib(n, a = 0, b = 1):
    seq = [a,b]
    while len(seq) < n:
        seq += [seq[len(seq)-1] + seq[len(seq)-2]]
    return seq

print(fib(13))

输出结果为:

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

或者:
#or if you want to make up your own
print(fib(13, 1597, 2584))

输出结果为:

[1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229]

2
问题出在最后一行。我相信这只是一个分心,你应该打印列表,而不是a
其他提示: 1:这整个块只是在重新创建由range返回的列表:
numberlist = []
i = 0
for i in range(20):
    numberlist.append(i)

i = 0 赋值也是无意义的。相反,可以尝试:
numberlist = range(20)

在Python 3中,调用list(range(20)),因为range不会创建一个完整的列表。
在循环的每次通过中重新定义fib函数不会创建问题,但这肯定是不必要的。将定义移至外部即可 :)

抱歉,伙计们,刚才才看到最后的评论!我马上开始。 - Da Bx

2

为了提高编程技能:你可以使用生成器itertools.islice()来获取前n个斐波那契数列:

from itertools import islice

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

fibonacci_numbers = list(islice(fib(), 20))
print(fibonacci_numbers)

输出

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]

1

斐波那契数列中的第n项是:

enter image description here 其中 enter image description here 并且 enter image description here

使用上述公式,可以使用列表推导式生成该序列:

[int(((((1 + math.sqrt(5)) / 2) ** x) - (((1 - math.sqrt(5)) / 2) ** (x))) / math.sqrt(5)) for x in range(n)] //where n is the number of terms in the series

1
我对其进行了概括,并考虑到了“range”或至少是“list(range())”会创建它自己的列表。
numberlist = list(range(20))

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

fibonaccinumbers = [fib(n) for n in numberlist]

print fibonaccinumbers

看起来它可以工作,打印出前20个斐波那契数列的每个值。我如何在不进行任何奇怪操作(例如:)的情况下调用 'fib(n)' 之外的 def:

a = fib(n)

那是我以前习惯的风格。不管怎样,现在程序看起来还好吗?


如果您按照 @J.F. Sebastian 的建议进行更改,程序将运行得更快。(因为它只会在 fib 循环中运行一次。) - Gort the Robot
好的,我会看看能否做到。 - Da Bx
你可能想查看所有的答案... 另外,请不要回答自己的问题,只是为了添加更多的问题,而是编辑您的问题。请参阅常见问题解答 - poke
好的,抱歉,非常感谢您的帮助。 不过我仍然不太确定生成器的作用。 我阅读了这个提示(https://dev59.com/7nVD5IYBdhLWcg3wDXJ3)。 - Da Bx

0

我只是使用公式并插入数值:

import math 

def Fibs(n):

 for i in range (n):

     Fn=int(((((1+math.sqrt(5))**i) - ((1-math.sqrt(5)) **i))/(2**i) * (math.sqrt(5)))/5)
     print (Fn)

Fibs(int(input())

0
为什么不使用列表推导式呢?这是我解决问题的方法。我会定义一个函数来计算斐波那契数列的第n个项,如下所示。
def fibo(n):
    if n<=2:
        return 1
    else:
        res = fibo(n-1) + fibo(n-2)
    return res

然后我会使用列表推导式来获取我想要的序列。
fib_sequence = [fibo(i) for i in range(n+1)]

0
def fibonacci(number):
        numbers = [0, 1]
        while len(numbers) < number:
            numbers[len(numbers):len(numbers)] = [numbers[len(numbers)-2] + numbers[len(numbers)-1]]
        return numbers

列表中的最后两个值在每次循环运行时相加。 在迭代到输入长度时,将使用每个新斐波那契值创建列表中的新位置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接