【发布时间】:2015-12-17 16:57:26
【问题描述】:
这是 Project Euler 问题 2:
斐波那契数列中的每个新项都是通过添加 前两期。从 1 和 2 开始,前 10 个术语将 是:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
通过考虑斐波那契数列中的项,其值不 超过四百万,求偶数项之和。
一种可能的直接方法是:
def fib_even(n):
previous, current = 0, 1
sum_fib = 0
while current <= n:
previous, current = current, previous + current
if current % 2 == 0:
sum_fib += current
return sum_fib
然后我尝试使用“纯”生成器以一种功能性的方式来完成它:
def fibonacci_generator():
curr_fib, next_fib = 0, 1
while True:
yield curr_fib
curr_fib, next_fib = next_fib, curr_fib + next_fib
print(sum(itertools.filterfalse(lambda x: x % 2 == 0, itertools.takewhile(lambda x: x < n, fibonacci_generator()))))
这个版本效率低下,因为同一个工作(屈服)被多次完成。
我的问题:生成斐波那契数一次的功能性方法是什么,直到达到某个限制并同时过滤奇数。 (不改变第二个版本的生成器。)
作为参考,第一个版本 timeit for 10 给出:
100000 loops, best of 3: 10 µs per loop
十亿的第二个版本timeit给出:
10000 loops, best of 3: 28.8 µs per loop
【问题讨论】:
-
这是函数式的方式。 Python 只是不支持具有与其他语言相同效率的函数式编程风格。
-
你已经有了函数式方式,而你的非函数式方式基本上是函数式方式,但是内联。也许如果这是 PyPy 或 Jython 之类的,系统可以 JIT 内联第二个版本以加快速度,但在 CPython 上,调用这些 lambda 对速度没有好处。
-
一个开箱即用的解决方案是注意每隔三个斐波那契数是偶数 (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...)。这意味着您可以只对序列进行切片,而不是测试每个值的均匀度。
标签: python python-3.x functional-programming