Sieve of Eratosthenes 的 Haskell/Scheme 实现

发布于 2022-08-14 10:59:54 字数 1603 浏览 16 评论 9

Sieve of Eratosthenes 算法描述见 http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

Haskell 实现如下:

  1. sieve :: [Integer] -> [Integer]
  2. sieve (x:xs) = x : sieve xs'
  3.              where xs' = filter (y -> y `mod` x /= 0) xs
  4. primes = 2 : sieve [3,5..]

复制代码

加了平方优化后的版本

  1. sieve :: [Integer] -> [Integer]
  2. sieve (x:xs) = x : sieve (xs' ++ xs''')
  3.              where
  4.                 (xs', xs'') = break (>= x*x) xs
  5.                 xs''' = filter (y -> y `mod` x /= 0) xs''
  6. primes = 2 : sieve [3,5..]

复制代码

实际上,第二个版本有严重的性能问题(break 会导致大量的内存操作)以至于还没有第一个快。

真正优化的版本(by win_hate):

  1. isPrime :: Integer -> [Integer] -> Bool
  2. isPrime p (x:xs)
  3.     | x*x > p           = True
  4.     | p `mod` x == 0    = False
  5.     | otherwise         = isPrime p xs
  6. primes = 2 : [ p | p <- [3,5..], isPrime p primes ]

复制代码

BTW,这个还可以再稍加优化。

[ 本帖最后由 MMMIX 于 2009-5-20 14:15 编辑 ]

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

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

发布评论

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

评论(9

谎言月老 2022-08-17 16:01:03

原帖由 win_hate 于 2008-9-21 17:44 发表

如果把语言选为 module,则得到一条错误。

估计是版本的问题,我看你用的还是 3.72, 我测试时用的是 4.1

collects/lazy/lang/reader.ss 这个文件在我这是有的,内容很简单:

  1. (module reader syntax/module-reader
  2.   lazy)

复制代码
[ 本帖最后由 MMMIX 于 2008-9-21 18:31 编辑 ]

橘香 2022-08-17 15:57:45

我不是很明白你的意思。

如果直接选 lazy scheme,是可以运行的。我回的第一贴用的就是这个环境

drs01.png (30.2 KB, 下载次数: 28)

下载附件

2008-09-21 17:48 上传

如果把语言选为 module,则得到一条错误。

drs02.png (33.41 KB, 下载次数: 26)

下载附件

2008-09-21 17:44 上传

可能我模块那里没写对?

[ 本帖最后由 win_hate 于 2008-9-21 17:49 编辑 ]

谢绝鈎搭 2022-08-17 15:52:49

原帖由 win_hate 于 2008-9-21 11:21 发表
谢谢!

用模块之后可以了,但对整个体系还是很模糊。要找个时间把 PLT 的文档好好看一看才行。

其实用 #lang 也是可以的,不过直接用 (list-ref primes 50) 是没有输出的,但是可以用 (display (list-ref primes 50)) 显示结果。

两相知 2022-08-17 15:28:53

谢谢!

用模块之后可以了,但对整个体系还是很模糊。要找个时间把 PLT 的文档好好看一看才行。

  1. (module nth (lib "lazy.ss" "lazy")
  2.   
  3.   (define odd
  4.     (letrec ((f (lambda (n)
  5.                   (cons n (f (+ n 2))))))
  6.       (f 3)))
  7.   
  8.   (define primes
  9.     (cons 2 (filter primes? odd)))
  10.   
  11.   (define (primes? n)
  12.     (define (f ps)
  13.       (let ((p (car ps)))
  14.         (cond ((> (* p p) n) #t)
  15.               ((= (modulo n p) 0) #f)
  16.               (else (f (cdr ps))))))
  17.     (f primes))
  18.   
  19.   (define (nth-prime n)
  20.     (! (list-ref primes n)))
  21.   
  22.   (provide nth-prime))

复制代码

友欢 2022-08-17 12:03:43

原帖由 win_hate 于 2008-9-21 10:17 发表
那个 #lang lazy 在 mzscheme 中好用吗?我这里试了不行。

mzscheme 不清楚(应该也行),我向来都是直接用 DrScheme 的
在 DrScheme 中应该把语言设为 Module,然后通过 #lang 选择具体要用的语言,这也是推荐的作法。

终陌 2022-08-17 01:50:41

原帖由 MMMIX 于 2008-9-21 01:59 发表
我觉着 integers 的定义可以优化下
PLT Scheme 实现

#lang lazy

(define (integers n)
  (cons n (integers (+ n 2))))

(define (sieve seq)
  (let ((p (car seq)))
  (cons p (sieve
         ...

说得对,用奇数列相当于在选材上先 filter 了一次。

那个 #lang lazy 在 mzscheme 中好用吗?我这里试了不行。

[ 本帖最后由 win_hate 于 2008-9-21 10:34 编辑 ]

余生共白头 2022-08-16 10:29:59

一个带平方优化的版本

  1. (define odd
  2.   (letrec ((f (lambda (n)
  3.              (cons n (f (+ n 2))))))
  4.     (f 3)))
  5. (define primes
  6.   (cons 2 (filter primes? odd)))
  7. (define (primes? n)
  8.   (define (f ps)
  9.     (let ((p (car ps)))
  10.       (cond ((> (* p p) n) #t)
  11.             ((= (modulo n p) 0) #f)
  12.             (else (f (cdr ps))))))
  13.   (f primes))

复制代码

南街女流氓 2022-08-16 04:25:48

我觉着 integers 的定义可以优化下
PLT Scheme 实现(需要在 DrScheme 中将语言设为 Module)

  1. #lang lazy
  2. (define (integers n)
  3.   (cons n (integers (+ n 2))))
  4. (define (sieve seq)
  5.   (let ((p (car seq)))
  6.   (cons p (sieve
  7.            (filter (lambda (x) (not (= 0 (modulo x p)))) (cdr seq))))))
  8.            
  9. (define primes (cons 2
  10.                      (sieve (integers 3))))

复制代码

  1. > (list-ref primes 50)
  2. 233

复制代码
[ 本帖最后由 MMMIX 于 2008-9-21 10:51 编辑 ]

无妨# 2022-08-14 20:24:10

lazy scheme

  1. (define (integers n)
  2.   (cons n (integers (+ n 1))))
  3. (define (sieve seq)
  4.   (let ((p (car seq)))
  5.   (cons p (sieve
  6.            (filter (lambda (x) (not (= 0 (modulo x p)))) (cdr seq))))))
  7.            
  8. (define primes (sieve (integers 2)))

复制代码

> (list-ref primes 50)
233

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