Python程序找到斐波纳契系列。更多Pythonic方式

时间:2009-02-23 16:53:23

标签: python

还有另一个线程来讨论Python中的Fibo系列。这是为了将代码调整为更加pythonic。 How to write the Fibonacci Sequence in Python

我爱上了我为解决Project Euler Q2而编写的这个程序。我在Python中进行新编码,每次使用Pythonic方式都会感到高兴!你能建议一个更好的Pythonic方法吗?

Project Euler Q2。找出Fibonacci序列中所有偶数项的总和,不超过四百万。

fib=[]
def fibo(a=-1,b=1,upto=4000000):
    if a+b>=upto:
        return
    else:
        a,b=b,a+b
        fib.append(b)
        fibo(a,b)

fibo()
even=[i for i in fib if not i%2]
print sum(even)

9 个答案:

答案 0 :(得分:16)

使用generator是一种Pythonic方法,可以在保留内存的同时生成长序列:

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

import itertools
upto_4000000 = itertools.takewhile(lambda x: x <= 4000000, fibonacci())
print(sum(x for x in upto_4000000 if x % 2 == 0))

答案 1 :(得分:14)

首先我将fibo()作为生成器:

def fibo(a=-1,b=1,upto=4000000):
    while a+b<upto:
        a,b = b,a+b
        yield b

然后我也选择将均匀度作为生成器而不是列表理解。

print sum(i for i in fibo() if not i%2)

答案 2 :(得分:4)

首先,我建议在计算它们时总结这些术语,而不是将它们存储在一个数组中,然后对数组进行求和,因为除了将它们添加起来之外,你不需要对各个术语做任何事情。 (这在任何语言中都是很好的计算意义)

答案 3 :(得分:2)

我会做出以下更改:

  • 使用迭代而不是递归
  • 只需保留一个总计,而不是保留所有斐波那契数字的列表,然后找到偶数的总和

除此之外,它合理地 Pythonic。

def even_fib_sum(limit):
    a,b,sum = 0,1,0
    while a <= limit:
        if a%2 == 0:
            sum += a
        a,b = b,a+b
    return sum

print(even_fib_sum(4000000))

答案 4 :(得分:2)

我在@constantin' answer中使用斐波纳契生成器,但生成器表达式可以用普通的for循环替换:

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

sum_ = 0
for f in fibonacci():
    if f > 4000000:
       break
    if f % 2 == 0:
       sum_ += f

print sum_

答案 5 :(得分:1)

这是另一种直接方法 它依赖于一些属性:

  1. 每个Fibonacci数可以直接计算为floor(pow(phi,n)+ 0.5)(参见http://en.wikipedia.org/wiki/Fibonacci_number中的舍入计算)。相反,最小斐波纳契数小于i的指数由楼层给出(log(i * sqrt(5))/ log(phi))
  2. 前N个Fibonacci数的总和是第N + 2个斐波那契数减1(参见同一个维基百科页面上的第二个身份)
  3. 偶数斐波那契数是每三个数。 (查看序列mod 2,结果很简单)
  4. 偶数Fibonacci数的总和是奇数Fibonacci数的总和的一半,直到序列中的同一点。
  5. 第4点可以从中看出:

    Sum of first 3N fibonacci numbers
       =(F(1) + F(2))+ F(3) +(F(4) + F(5))+ F(6) + ... +(F(3N-2) + F(3N-1))+ F(3N) 
       =     F(3)    + F(3) +     F(6)    + F(6) + ... +       F(3N)       + F(3N)
       = 2( F(3) + F(6) + ... + F(3N) )
       = 2 ( Sum of odd fibonacci numbers up to F(3N) )
    

    因此转换我们的最大值4000000计算最高斐波那契数的索引 少于它。

    int n = floor(log(4000000*sqrt(5))/log(phi));  // ( = 33) 
    

    33可被3整除,因此它是一个偶数斐波纳契数,如果不是,我们需要像这样调整n。

    n = (n/3)*3;
    

    如果由

    给出,所有斐波纳契数的总和到此为止
    sum = floor( pow( phi, n+2 ) + 0.5 ) - 1; // ( = 9227464 )
    

    所有偶数的总和是这个数字的一​​半:

    sum_even = sum/2; // ( = 4613732 )
    

    关于这一点的好处是它是一个O(1)(或O(log(N)),如果你包括pow / log成本算法,并且工作在双打..所以我们可以计算非常的总和很大的价值观。

    注意:我编辑并从这个问题的封闭副本中移动了这个答案。 Fibonacci under 4 millions

答案 6 :(得分:0)

在Python 3中,至少如果你给sum函数一个生成器,它会懒惰地评估它,所以不需要重新发明轮子。

这就是@Constantin所做的并且是正确的。

通过比较使用生成器的内存使用情况进行测试:

sum(range(9999999))

与不这样做相比:

sum(list(range(9999999)))

具有生成器的那个不会导致具有更高数字的内存异常。

答案 7 :(得分:0)

print ("Fibonacci Series\n")

a  = input ("Enter a nth Term: ")

b = 0 

x = 0

y = 1

print x,("\n"), y

while b <=a-2:

  b = b+1

  z = x + y

  print z

  x = y

  y = z

答案 8 :(得分:0)

def main():
    a = 1
    b = 2
    num = 2

    while b < 4000000:
        a, b = b, a+b
        num += b if b % 2 == 0 else 0

    print num

if __name__ == '__main__':
    main()