斐波那契数的总和

时间:2010-05-05 20:52:19

标签: haskell fibonacci

我对Haskell很新。问题是找到所有偶数Fibonacci数不超过4百万的总和。我不能使用列表。

如果我理解正确,下面的解决方案是错误的,因为它使用列表:

my_sum = sum $ filter (odd) $ takeWhile (< 4000000) fibs

其中 fibs 是所有Fibonacci数字的列表。

不知何故,我发现很难不在Haskell中考虑列表。任何人都可以指导我解决这个问题吗?

此致

编辑:

如果有人有兴趣,我已经解决了这个问题。这是代码(非常笨拙,但仍然有效):

findsum threshold = findsum' 0 1 0 threshold


findsum' n1 n2 accu t 
| n2 > t    = accu
| odd n2    = findsum' n2 n3 accu t 
| otherwise = findsum' n2 n3 accu2 t
where
    n3 = n2 + n1
    accu2 = accu + n2

3 个答案:

答案 0 :(得分:5)

您可能会发现在excel中构建它更容易,然后从那里找出代码。在excel中很容易做到这一点。只需将1放在第一个单元格中,然后将1放在它下面。然后让下面的每个单元格添加上面的两个单元格。 (即,单元格a3包含= A1 + A2)。使下一列仅包含偶数值“ie,if(mod(a3,2)== 0,a3,0)”。接下来,将您的运行总和放在第三列中。基于此,您应该能够提出递归解决方案。

另一种方法是从问题开始。你只想要一个为累加器尖叫的总数。

sumFib :: Integer -> Integer
sumFib threshold = sumFib' 1 1 0 threshold

sumFib' :: Integer -> Integer -> Integer -> Integer -> Integer
sumFib' n1 n2 acc threshold

您可以在上面看到我的功能的签名。我建立了一个漂亮的前端,需要一个阈值(4,000,000)来决定何时退出建立斐波那契数字。然后我把这个加上前2个斐波纳契数和一个累加器传递给工作函数“sumFib”,它执行递归。瞧...答案,“4613732”,没有清单......

n1是n-1斐波那契数,n2是n-2斐波纳契数。

希望有所帮助。

编辑:这是我的完整解决方案:

sumFib :: Integer -> Integer
sumFib threshold = sumFib' 1 1 0 threshold

sumFib' :: Integer -> Integer -> Integer -> Integer -> Integer
sumFib' n1 n2 acc threshold
     | n1 > threshold = acc
     | otherwise = sumFib' (n2+n1) n1 newAcc threshold
            where newAcc = if n1 `mod` 2 == 0
                               then n1 + acc
                               else acc

答案 1 :(得分:3)

您可以使用continuation-passing style在没有列表的情况下使用递归解决方案执行此操作。

BTW运行所有斐波那契数并过滤掉奇数数字是解决这个问题的缓慢方法。

答案 2 :(得分:3)

同样,计算机有用程度的非示例:

你可以在没有电脑的情况下完成这项工作!

第一次观察:每三个Fibo数是偶数,第一个甚至Fibo数是F_3 = 2

确实:奇数+奇数=偶数;奇数偶数+ =奇数;偶数+奇数=奇数,已经关闭了圆圈

第二次观察:F_3 + F_6 + F_9 + ... + F_ {3k} = 1/2(F_ {3k + 2} - 1)

归纳:F_3 = 2 = 1/2(5 - 1)= 1/2(F_5 - 1)

F_3 + F_6 + ... + F_ {3k + 3} = 1/2(F_ {3k + 2} - 1)+ F_ {3k + 3} = 1/2(F_ {3k + 2} + 2F_ {3k + 3} -1)= 1/2(F_ {3k + 4} + F_ {3k + 3} -1)= 1/2(F_ {3k + 5} -1)

第3次观察:总和将有1333333个加数,最后一个是第3999999个Fibo数。

第4次观察:F_n = 1 / sqrt(5)*(phi ^ n - (1-phi)^ n)

Proof by Wikipedia

现在,我们可以把各个部分放在一起: F_3 + F_6 + ... + F_3999999 = 1/2(F_4000001 - 1)= 1/2 1 / sqrt(5)(phi ^ 4000001 - (1-phi)^ 4000001) - 1/2 = int(1 / 2 1 / sqrt(5)phi ^ 4000001)

这里int是整数部分。最后一步是有效的,因为-1&lt; 1-phi&lt; 0等(1-phi)^ 4000001几乎消失。您可能希望使用计算器来获取数值。