Haskell 脚本空间不足

发布于 2024-07-17 01:11:42 字数 516 浏览 6 评论 0原文

我正在使用 Euler 项目自学 Haskell,但我在推理 Haskell 如何执行我的代码时遇到了一些麻烦。 第二个问题让我计算 400 万以内所有偶数斐波那契数的总和。 我的脚本如下所示:

fibs :: [Integer]
fibs =  1 : 2 : [ a+b | (a,b) <- zip fibs (tail fibs)]

evens  :: Integer -> Integer -> Integer
evens x sum | (even x)   = x + sum
            | otherwise  = sum

main = do
  print (foldr evens 0 (take 4000000 fibs))

Hugs 给出错误“垃圾收集无法回收足够的空间”,我认为这意味着列表条目在被 foldr 消耗时不会被释放。

我需要做什么来解决这个问题? 我尝试编写一个使用累加器的尾递归(我认为)版本,但也无法使其工作。

I'm using project Euler to teach myself Haskell, and I'm having some trouble reasoning about how my code is being executed by haskell. The second problem has me computing the sum of all even Fibonacci numbers up to 4 million. My script looks like this:

fibs :: [Integer]
fibs =  1 : 2 : [ a+b | (a,b) <- zip fibs (tail fibs)]

evens  :: Integer -> Integer -> Integer
evens x sum | (even x)   = x + sum
            | otherwise  = sum

main = do
  print (foldr evens 0 (take 4000000 fibs))

Hugs gives the error "Garbage collection fails to reclaim sufficient space", which I assume means that the list entries are not released as they are consumed by foldr.

What do I need to do to fix this? I tried writing a tail-recursive (I think) version that used accumulators, but couldn't get that to work either.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

偏闹i 2024-07-24 01:11:42

首先,你不应该拥抱。 它只是一个仅用于教学目的的玩具。

然而,GHC 是 Haskell 的快速、多核就绪优化编译器。 在此处获取。 特别是,它进行严格性分析,并编译为本机代码。

您的代码中最突出的一点是在一个非常大的列表上使用foldr。 也许您想要一个尾递归循环。 像这样:

import Data.List

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

evens x sum | even x    = x + sum
            | otherwise = sum

-- sum of even fibs in first 4M fibs
main = print (foldl' evens 0 (take 4000000 fibs))

除此之外,前 4M 偶数 fib 将使用相当多的空间,因此需要一段时间。

这是前 400k 个偶数 fib 的总和,以节省您一些时间(21 秒)。 :-)

Firstly, you shouldn't use hugs. It is a toy for teaching purposes only.

GHC, however, is a fast, multicore-ready optimizing compiler for Haskell. Get it here. In particular, it does strictness analysis, and compiles to native code.

The main thing that stands out about your code is the use of foldr on a very large list. Probably you want a tail recursive loop. Like so:

import Data.List

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

evens x sum | even x    = x + sum
            | otherwise = sum

-- sum of even fibs in first 4M fibs
main = print (foldl' evens 0 (take 4000000 fibs))

Besides all this, the first 4M even fibs will use a fair amount of space, so it'll take a while.

Here's the sum of the first 400k even fibs, to save you some time (21s). :-)

≈。彩虹 2024-07-24 01:11:42

一些观察/提示:

  • 偶数中的 x + sum 直到最后才被计算
  • 您正在取前 4,000,000 个小纤维,而不是最多 4,000,000 个小纤维
  • 有一种更简单的方法要执行此

操作编辑以回复评论

我不会告诉您更简单的方法是什么,因为这就是欧拉项目问题的乐趣所在。 但我会问你一堆问题:

  • 你能连续说多少个偶数小谎?
  • 你能坚持多久而不撒谎?
  • 如果您将所有偶数小纤维和所有奇数小纤维相加(手动计算),您会注意到这些总和是什么?

A number of observations / hints:

  • the x + sums from even aren't getting evaluated until the very end
  • You're taking the first 4,000,000 fibs, not the fibs up to 4,000,000
  • There is an easier way to do this

Edit in response to comment

I'm not going to tell you what the easier way is, since that's the fun of Project Euler problems. But I will ask you a bunch of questions:

  • How many even fibs can you have in a row?
  • How long can you go without an even fib?
  • If you sum up all the even fibs and all the odd fibs (do this by hand), what do you notice about the sums?
旧街凉风 2024-07-24 01:11:42

你对问题的理解是错误的。 实际问题希望您将所有偶数斐波那契数相加,使得斐波那契数本身不超过 400 万(恰好是前 33 个斐波那契数)。

You understood the problem wrong. The actual problem wants you to sum all the even Fibonacci numbers such that the Fibonacci number itself doesn't exceed 4 million (which happens to be only the first 33 Fibonacci numbers).

挽容 2024-07-24 01:11:42

您正在评估 400 万个 fibs 元素。 这些数字呈指数级增长。 我不知道需要多少字节来表示第一百万个斐波那契数; 仅千分之一的斐波那契数就有 211 个十进制数字,因此仅需要 22 个 32 位字来保存这些数字,更不用说 gmp 带来的任何开销。 而且这些都呈指数级增长。

练习:计算保存 400 万个斐波那契数所需的内存量。

You are evaluating four million elements of fibs. Those numbers grow exponentially. I don't know how many bytes are required to represent the millionth Fibonacci number; just the one-thousandth Fibonacci number has 211 decimal digits, so that's going to take 22 32-bit words just to hold the digits, never mind whatever overhead gmp imposes. And these grow exponentially.

Exercise: calculuate the amount of memory needed to hold four million Fibonacci numbers.

束缚m 2024-07-24 01:11:42

看一下 Prelude 函数 takeWhile、filter、even 和 sum

takeWhile (<40) [0..]
过滤偶数 $ takeWhile (<40) [0..]

将它们放在一起:

ans = sum $ 过滤偶数 $ takeWhile (< 4* 10^6) fibs

have a look at the Prelude functions takeWhile, filter, even, and sum

takeWhile (<40) [0..]
filter even $ takeWhile (<40) [0..]

put 'em together:

ans = sum $ filter even $ takeWhile (< 4* 10^6) fibs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文