如何在 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 的质数。