【问题标题】:sum of even fibonacci numbers up to 4million偶数斐波那契数的总和高达 400 万
【发布时间】:2014-03-14 12:27:28
【问题描述】:

我用来尝试解决这个问题的方法有效,但我认为它不是很有效,因为一旦我输入了一个太大的数字,它就不起作用了。

def fib_even(n):
    fib_even = []
    a, b = 0, 1
    for i in range(0,n):
        c = a+b
        if c%2 == 0:
            fib_even.append(c)
            a, b = b, a+b
return fib_even

def sum_fib_even(n):
    fib_evens = fib_even(n)
    s = 0
    for i in fib_evens:
        s = s+i
    return s

n = 4000000
answer = sum_fib_even(n)
print answer

例如,这不适用于 4000000,但适用于 400。有更有效的方法吗?

【问题讨论】:

  • 在这篇文章中,提供了许多技术:stackoverflow.com/questions/18172257/…
  • a, b = b, a+b 应该在if 块之外。
  • 如果那是 Project Euler 问题 2,那你就看错了。
  • “不起作用”是什么意思?错误答案、异常、崩溃?
  • “我用来尝试解决这个问题的方法有效”。你确定吗?对于我给它的任何输入,它只会给我零。这是在修复了return fib_even 的错误缩进之后。您能在这里仔细检查一下您的代码格式是否正确吗?

标签: python math fibonacci


【解决方案1】:

没有必要计算所有的斐波那契数。

注意:我在后面使用斐波那契数列更标准的初始值 F[0]=0, F[1]=1。 Project Euler #2 以 F[2]=1,F[3]=2,F[4]=3,.... 开始其序列。对于这个问题,任一选择的结果都是相同的。

所有斐波那契数的总和(作为热身)

递归方程

F[n+1] = F[n] + F[n-1]

也可以读作

F[n-1] = F[n+1] - F[n]

F[n] = F[n+2] - F[n+1]

将 n 从 1 到 N 相加(记住 F[0]=0,F[1]=1)在左侧给出斐波那契数的总和,在右侧给出一个伸缩总和,其中所有内部条款取消

sum(n=1 to N) F[n] = (F[3]-F[2]) + (F[4]-F[3]) + (F[5]-F[4])
                     + ... + (F[N+2]-F[N+1])
                   = F[N+2] - F[2] 

因此,对于使用问题的数字 N=4,000,000 的总和,人们只需计算即可

F[4,000,002] - 1

使用计算单个斐波那契数的超快速方法之一。要么是对半平方,相当于对迭代矩阵求幂,要么是基于黄金比例的指数公式(以必要的精度计算)。

由于大约每 20 个斐波那契数增加 4 个数字,最终结果将包含大约 800000 个数字。最好使用可以包含所有这些的数据类型。


偶数斐波那契数的总和

仅检查前 10 或 20 个斐波那契数即可发现所有偶数成员的索引均为 3*k。检查通过减去两个连续的递归得到

F[n+3]=2*F[n+2]-F[n]

所以 F[n+3] 总是与 F[n] 具有相同的奇偶性。投入更多的计算会发现成员的递归三个索引分开为

F[n+3] = 4*F[n] + F[n-3]

设置

S = sum(k=1 to K) F[3*k]

对 n=3*k 的递归求和

F[3*K+3]+S-F[3] = 4*S + (-F[3*K]+S+F[0])

4*S = (F[3*K]+F[3*K]) - (F[3]+F[0]) = 2*F[3*K+2]-2*F[2]

所以想要的总和有公式

S = (F[3*K+2]-1)/2

使用黄金比例公式快速计算得出 N 应该是多少,这样 F[N] 就在边界下方,因此 K=N div 3 应该是多少,

N = Floor(  log( sqrt(5)*Max )/log( 0.5*(1+sqrt(5)) )  )

将欧拉问题简化为一个简单的公式

在原始问题中,发现 N=33,因此总和为

S = (F[35]-1)/2;

减少问题中的问题和后果

取题中错误表述的问题,N=4,000,000,所以K=1,333,333,总和为

(F[1,333,335]-1)/2

仍然有大约 533,400 位数字。是的,大整数类型可以处理这样的数字,只是需要时间来计算。

如果以 60 行和 80 位的格式打印,这个数字会填满 112 张纸,只是想知道输出会是什么样子。

【讨论】:

  • Python 可以存储几乎任何大小的整数,但仅限于可用(和可寻址)内存。 4,000,000 / 20 == 200,000,不是800,000
  • 是的,200,000 块 20 个斐波那契数字,每个块之后,数字长 4 位,总共 800,000 位。然而,这个问题被严重错误地陈述了,原问题的解决只需要所有 F[3*k] 到 F[33] 或者用一个聪明的公式只需要 F[35]。
【解决方案2】:

没有必要存储所有中间斐波那契数,也许存储会导致性能问题。

【讨论】:

  • 没错,但它只存储偶数,大多数计算机可以轻松存储多达 400 万个数字的列表。测试你的理论也很容易,那你为什么不呢?
  • 更重要的是,存储所有中间斐波那契数可以避免它们被多次重新计算。存储它们是使用动态编程提高斐波那契效率的教科书示例。
猜你喜欢
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多