如何在 Forth 中构建素数生成器?
How to build a prime generator in Forth?
我的目标是用 Forth 构建一个素数生成器。不是埃拉托色尼筛法,而是两个嵌套循环,它们暴力破解数字 A 和数字 B 的所有组合。在源代码中,我有一个关于循环的词,用于测试条件是否为真以及进行嵌套循环的一些尝试。但是在使用 gforth 执行代码后,会显示堆栈下溢错误。也许某处缺少某种 dup,但循环中的 i 和 j 索引也可能是错误的。问题是,如果我更改代码中的某些内容,堆栈就会不同。这意味着,在将 for 循环的索引号输出到屏幕后,将无法再访问该编号。我还发现很难访问变量,因为 Forth 似乎根本没有变量。所以我创建了一个辅助变量,但不清楚如何使用它。
我知道,代码看起来有点混乱,有人可以帮忙吗?
variable temp
: numbers
10 0 do i . loop
;
: cond
0 dup
0 = if ." equal 0" endif
;
: plain
10 2 mod .
10 3 mod .
10 4 mod .
10 5 mod .
10 6 mod .
10 7 mod .
10 8 mod .
10 9 mod .
;
: plain2
10 temp !
\ 10 0 do temp @ i mod . loop
\ 10 0 do temp @ . i . loop
10 2 do temp @ i mod . cond loop
;
: cond2 ( n - n )
10 2 do i
10 2 do i
mod .
loop cr loop
;
: main
\ numbers
cond2
\ plain
\ plain2
;
main
CR bye
您的代码中存在多个错误和重复。例如,在您的 cond
字词中,您将 0
放在数据堆栈上,然后 dup
并将堆栈顶部值(即 0
)与 0
进行比较。当然每次都会得到true
您似乎试图一次编写许多单词定义并在您的程序中使用它们,而没有仔细调试每个单词。对于 Forth
编程,最好制作(和调试)几个简短的单词,然后用它们编写更复杂的代码。我建议您阅读 Starting Forth book,它很好地描述了这种方法。
关于您的代码——最好完全重写它。这是:
: is-not-divided-by mod 0= INVERT ;
: check-prime-number true SWAP DUP 2 DO DUP I is-not-divided-by ROT AND SWAP loop DROP ;
: is-prime-number DUP 2 > IF check-prime-number ELSE DROP true THEN ;
: prime-numbers 1 DO I is-prime-number IF I . THEN LOOP ;
现在 10 prime-numbers
将为您打印从 1 到 9 的质数。
我的目标是用 Forth 构建一个素数生成器。不是埃拉托色尼筛法,而是两个嵌套循环,它们暴力破解数字 A 和数字 B 的所有组合。在源代码中,我有一个关于循环的词,用于测试条件是否为真以及进行嵌套循环的一些尝试。但是在使用 gforth 执行代码后,会显示堆栈下溢错误。也许某处缺少某种 dup,但循环中的 i 和 j 索引也可能是错误的。问题是,如果我更改代码中的某些内容,堆栈就会不同。这意味着,在将 for 循环的索引号输出到屏幕后,将无法再访问该编号。我还发现很难访问变量,因为 Forth 似乎根本没有变量。所以我创建了一个辅助变量,但不清楚如何使用它。
我知道,代码看起来有点混乱,有人可以帮忙吗?
variable temp
: numbers
10 0 do i . loop
;
: cond
0 dup
0 = if ." equal 0" endif
;
: plain
10 2 mod .
10 3 mod .
10 4 mod .
10 5 mod .
10 6 mod .
10 7 mod .
10 8 mod .
10 9 mod .
;
: plain2
10 temp !
\ 10 0 do temp @ i mod . loop
\ 10 0 do temp @ . i . loop
10 2 do temp @ i mod . cond loop
;
: cond2 ( n - n )
10 2 do i
10 2 do i
mod .
loop cr loop
;
: main
\ numbers
cond2
\ plain
\ plain2
;
main
CR bye
您的代码中存在多个错误和重复。例如,在您的 cond
字词中,您将 0
放在数据堆栈上,然后 dup
并将堆栈顶部值(即 0
)与 0
进行比较。当然每次都会得到true
您似乎试图一次编写许多单词定义并在您的程序中使用它们,而没有仔细调试每个单词。对于 Forth
编程,最好制作(和调试)几个简短的单词,然后用它们编写更复杂的代码。我建议您阅读 Starting Forth book,它很好地描述了这种方法。
关于您的代码——最好完全重写它。这是:
: is-not-divided-by mod 0= INVERT ;
: check-prime-number true SWAP DUP 2 DO DUP I is-not-divided-by ROT AND SWAP loop DROP ;
: is-prime-number DUP 2 > IF check-prime-number ELSE DROP true THEN ;
: prime-numbers 1 DO I is-prime-number IF I . THEN LOOP ;
现在 10 prime-numbers
将为您打印从 1 到 9 的质数。