帮助理解埃拉托斯特尼筛法的实现
我知道这很无聊,但我需要一些帮助来理解埃拉托斯特尼筛法的实现。这是这个编程实践问题的解决方案。
(define (primes n)
(let* ((max-index (quotient (- n 3) 2))
(v (make-vector (+ 1 max-index) #t)))
(let loop ((i 0) (ps '(2)))
(let ((p (+ i i 3)) (startj (+ (* 2 i i) (* 6 i) 3)))
(cond ((>= (* p p) n)
(let loop ((j i) (ps ps))
(cond ((> j max-index) (reverse ps))
((vector-ref v j)
(loop (+ j 1) (cons (+ j j 3) ps)))
(else (loop (+ j 1) ps)))))
((vector-ref v i)
(let loop ((j startj))
(if (<= j max-index)
(begin (vector-set! v j #f)
(loop (+ j p)))))
(loop (+ 1 i) (cons p ps)))
(else (loop (+ 1 i) ps)))))))
我遇到问题的部分是 startj
。现在,我可以看到 p
将从 3 开始循环奇数,定义为 (+ ii 3)
。但我不明白p
和startj
之间的关系,即(+ (* 2 ii) (* 6 i) 3)
。
编辑:我知道这个想法是跳过以前筛选的数字。谜题定义指出,当筛选数字 x
时,筛选应从 x
的平方开始。因此,当筛选 3 时,首先消除 9 等。
但是,我不明白的是作者如何想出 startj
的表达式(从代数角度来说)。
来自拼图评论:
一般来说,当按n筛选时,筛选从n次方开始,因为之前所有n的倍数都已被筛选。
表达式的其余部分与数字和筛索引之间的交叉引用有关。表达式中有一个 2,因为我们在开始之前就消除了所有偶数。表达式中有 3,因为Scheme 向量是从零开始的,并且数字 0、1 和 2 不是筛子的一部分。我认为 6 实际上是 2 和 3 的组合,但是我已经有一段时间没有查看代码了,所以我将它留给你来弄清楚。
如果有人能帮助我解决这个问题,那就太好了。谢谢!
This is boring, I know, but I need a little help understanding an implementation of the Sieve of Eratosthenes. It's the solution to this Programming Praxis problem.
(define (primes n)
(let* ((max-index (quotient (- n 3) 2))
(v (make-vector (+ 1 max-index) #t)))
(let loop ((i 0) (ps '(2)))
(let ((p (+ i i 3)) (startj (+ (* 2 i i) (* 6 i) 3)))
(cond ((>= (* p p) n)
(let loop ((j i) (ps ps))
(cond ((> j max-index) (reverse ps))
((vector-ref v j)
(loop (+ j 1) (cons (+ j j 3) ps)))
(else (loop (+ j 1) ps)))))
((vector-ref v i)
(let loop ((j startj))
(if (<= j max-index)
(begin (vector-set! v j #f)
(loop (+ j p)))))
(loop (+ 1 i) (cons p ps)))
(else (loop (+ 1 i) ps)))))))
The part I'm having trouble with is startj
. Now, I can see that p
is going to be cycling through odd numbers starting at 3, defined as (+ i i 3)
. But I don't understand the relationship between p
and startj
, which is (+ (* 2 i i) (* 6 i) 3)
.
Edit: I understand that the idea is to skip previously sifted numbers. The puzzle definition states that when sifting a number x
, sifting should start at the square of x
. So, when sifting 3, start by eliminating 9, etc.
However, what I don't understand is how the author came up with that expression for startj
(algebraically speaking).
From the puzzle comments:
In general, when sifting by n, sifting starts at n-squared because all the previous multiples of n have already been sieved.
The rest of the expression has to do with the cross-reference between numbers and sieve indexes. There’s a 2 in the expression because we eliminated all the even numbers before we ever started. There’s a 3 in the expression because Scheme vectors are zero-based, and the numbers 0, 1 and 2 aren’t part of the sieve. I think the 6 is actually a combination of the 2 and the 3, but it’s been a while since I looked at the code, so I’ll leave it to you to figure out.
If anyone could help me with this, that'd be great. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想我已经在programmingpraxis的评论的帮助下找到了答案他们的网站。
为了重述该问题,
startj
在清单中定义为(+ (* 2 ii) (* 6 i) 3)
,即2i^2 + 6i + 3
。我最初并不理解这个表达式如何与
p
相关 - 因为数字p
的“筛选”应该从p^2
开始,我我认为startj
应该与4i^2 + 12i + 9
相关。但是,
startj
是向量v
的索引,其中包含从 3 开始的奇数。因此,p^2
的索引实际上是(p^2 - 3) / 2
。展开方程:
(p^2 - 3) / 2
=([4i^2 + 12i + 9] - 3) / 2
=2i^2 + 6i + 3
- 这是startj
的值。我觉得将
startj
定义为(quotient (- (* pp) 3) 2)
可能会更清楚,但无论如何 - 我认为这解决了它:)I think I've figured it out, with the assistance of programmingpraxis' comments on their website.
To restate the problem,
startj
is defined in the listing as(+ (* 2 i i) (* 6 i) 3)
, i.e.2i^2 + 6i + 3
.I didn't initially understand how this expression related to
p
- since 'sifting' for a numberp
should start atp^2
, I figured thatstartj
should be something relating to4i^2 + 12i + 9
.However,
startj
is an index into the vectorv
, which contains odd numbers starting from 3. Therefore, the index forp^2
is actually(p^2 - 3) / 2
.Expanding the equation:
(p^2 - 3) / 2
=([4i^2 + 12i + 9] - 3) / 2
=2i^2 + 6i + 3
- which is the value ofstartj
.I feel it might've been clearer to define
startj
as(quotient (- (* p p) 3) 2)
, but anyway - I think that solves it :)David Seiler:也许不是最清楚,但除了实现基本的 Sieve 之外,它还必须实现练习中描述的三个优化。
哈托:这是我的第二个练习。我仍在尝试我的写作风格。
埃菲米特:正确。
请参阅我的评论中的更完整的解释 Programming Praxis 。
编辑:我在编程实践中添加了一条附加评论。而当我真正看代码时,我对公式中数字6的推导是错误的;抱歉我误导了你。
David Seiler: perhaps not the clearest, but in addition to implementing the basic Sieve it also has to implement the three optimizations described in the exercise.
Harto: that was my second exercise. I was still experimenting with my writing style.
Ephemient: correct.
See a more complete explanation in my comment at Programming Praxis.
EDIT: I've added an additional comment at Programming Praxis. And when I actually looked at the code, I was wrong about the derivation of the number 6 in the formula; sorry I mislead you.