【问题标题】:Sum of Fibonacci numbers斐波那契数之和
【发布时间】:2011-02-16 03:05:01
【问题描述】:

我对 Haskell 比较陌生。问题是找到不大于 400 万的所有偶数斐波那契数的总和。我不能使用列表。

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

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

其中 fibs 是所有斐波那契数列。

不知何故,我发现在 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

【问题讨论】:

  • 这是作业吗?你已经尝试过什么?
  • 不是作业 - 欧拉计划。前几天我刚做了这个确切的问题。
  • 为什么不能使用列表?
  • @mjboggess:我写了一个基于列表的解决方案。我正在寻找有关如何在没有列表的情况下执行此操作的提示。
  • @Rafal - 但为什么呢?在 Haskell 中,有一个合适的 fibs 定义——即使有一个列表,它也是惰性的。您最好让所有出色的机器完成工作并直接表达解决方案。如果 fibs 定义正确,内存中永远不会存在实际的列表!

标签: haskell fibonacci


【解决方案1】:

您可能会发现在 excel 中构建它然后从那里找出代码更容易。在excel中很容易做到这一点。只需将 1 放在第一个单元格中,然后将 1 放在其下方。然后使下面的每个单元格都添加上面的两个。 (即,单元格 a3 包含 =A1+A2)。使下一列仅包含偶数值“即 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

【讨论】:

  • 很高兴为您提供帮助!写 java 是一个有趣的休息:)
【解决方案2】:

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

顺便说一句,遍历所有斐波那契数并过滤掉奇数是解决此问题的缓慢方法。

【讨论】:

  • 感谢您的链接。我会检查的。
【解决方案3】:

再次,一个非示例说明计算机的用途:

不用电脑也能做到!

第一个观察:每隔三个斐波纳奇数是偶数,第一个偶数斐波纳奇数是 F_3=2

确实:奇+奇=偶;奇数+偶数=奇数; even+odd=odd,这已经是闭环了

第二次观察: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)

第三个观察结果:总和将有 1333333 个和数,最后一个是第 3999999 个斐波纳奇数。

第四次观察: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

【讨论】:

    猜你喜欢
    • 2015-07-25
    • 1970-01-01
    • 2011-02-04
    • 2016-07-23
    • 2016-04-07
    • 2015-11-12
    • 2015-06-05
    • 2014-05-23
    • 2014-05-03
    相关资源
    最近更新 更多