从评论中我最感兴趣的是:
问题:2
通过考虑Fibonacci序列中值不超过400万的项,找出偶数项的和。
import math
import itertools
#----------------------------------------------------------------------------------
def calc_fibonacci_num(n):
"""Calculates the fibonacci number at the given index.
Arguments:
type:<int> - Index value of the fibonacci sequence
Return:
type:<int> - Fibonacci number at the given index.
"""
return int(((1 + math.sqrt(5))**n -(1 - math.sqrt(5))**n)/(2**n*math.sqrt(5)))
#----------------------------------------------------------------------------------
def calc_fibonacci_seq(n):
"""Generates the fibonacci sequence with the highest
value equal to or less then the number provided by the user.
Arguments:
type:<int> - Thrshold value for the fibonacci sequence.
Return:
type:<arr> - An array holding the fibonacci sequence.
"""
return [calc_fibonacci_num(x) for x in itertools.takewhile(lambda x: calc_fibonacci_num(x) <= n, itertools.count())]
#----------------------------------------------------------------------------------
def calc_fibonacci_sum(n, d = 0):
"""Calculates the sum of the numbers in fibonacci sequence.
Filtering of the numbers to be added is controled with the module operator.
Arguments:
type:<int> - Thrshold value for the fibonacci sequence.
type:<int> - Division value for module operation.
Return:
type:<int> - The sum of the numbers in the fibonacci sequence.
"""
if d > 1 :
return sum(x for x in calc_fibonacci_seq(n) if x % d == 0)
return sum(x for x in calc_fibonacci_seq(n))
#----------------------------------------------------------------------------------
def main():
print(' Fibonacci-seq : {}'.format(calc_fibonacci_seq(4000000)))
print(' Fibonacci-sum : {}'.format(calc_fibonacci_sum(4000000, 2)))
#----------------------------------------------------------------------------------
if __name__ == "__main__":
main()
发布于 2017-12-06 14:13:37
您的代码看起来很好,并且有很好的文档。不管怎样,我有几个建议。
calc_fibonacci_num
是这样一个函数的长名称。calc_
前缀可能没用,_num
也没用。
表达式fibonacci(5)
可能足够显式,而不需要其他信息。
同样的注释也适用于其他函数名。
将d=0
作为calc_fibonacci_sum
的特例似乎有点“不自然”。可以更清楚地解释,d
应该是一个严格的正整数。
然后,您只需要给d
默认值1,一切都会正常工作。
在return [calc_fibonacci_num(x) for x in itertools.takewhile(lambda x: calc_fibonacci_num(x) <= n, itertools.count())]
中,使用相同的参数调用相同的函数两次。您可以通过在print(n)
的开头添加一个calc_fibonacci_num
来轻松地检查这一点。
解决此问题的一个方法是重写该函数:
def calc_fibonacci_seq(n):
return itertools.takewhile(lambda x: x <= n, (calc_fibonacci_num(x) for x in itertools.count()))
这修复了另一个问题,即在内存中构建一个实际的列表时,只需要一个生成器来遍历不同的列表。
的一种更简便的方法
您所使用的公式对于生成n个斐波那契数是相当有效的,而不需要生成之前的所有数字。然而,在我们的例子中,我们确实需要计算它们。因此,天真的解决方案可能会更快。我建议使用以下发电机:
def fibo(f=1, g=1):
"""Yields Fibonacci numbers."""
while True:
yield f
f, g = g, f + g
发布于 2017-12-06 16:15:33
calc_fibonacci_num没有提到接受的输入范围
>>> calc_fibonacci_num(100)
354224848179263111168L
根据wolframalpha,电话号码是354224848179261915075
浮点算法不够精确,无法处理这一问题。
发布于 2017-12-06 18:00:15
由于Josay已经对代码本身进行了广泛的讨论,请允许我在性能方面再加两分钱。
一些欧拉问题都是针对初学者和有经验的程序员的,第二个问题就是其中之一。初学者像你一样处理这个问题,并按要求逐个实现解决方案。更有经验的程序员模糊地记得一些关于几何级数的内容,并通过首先搜索Fibonacci索引n
来实现解决方案,生成一个低于极限M
的值:
n = floor(log(M*sqrt(5))/ log((1+sqrt(5)) / 2 ))
(当心:这给了F(n) <= M
!)对于具有默认M <= 2^64
精度的double
来说,它已经足够好了。
到并包含n
的偶数斐波纳契指数之和是F(2n + 1) -1
(通过伸缩级数和在https://math.stackexchange.com/questions/1159572/prove-the-sum-of-the-even-fibonacci-numbers进行归纳来证明)。
该方法将F(n)的计算次数减少到一次(或者两次,如果限制为F(n) < M
),虽然需要一个大得多的(Python有一个内置的bigint库,因为版本>2.5)才能得到最终的结果,但如果您将F(n)
的求值作为矩阵指数来实现,那么计算速度还会更快。
https://codereview.stackexchange.com/questions/182146
复制相似问题