虽然不完全符合您的要求,但这里提供了一个更习惯用语和快得多的筛法版本。
基本上,您需要检查哪个数字是哪个数字的倍数。您可以从模表中获取此信息:|/~
l =: 2 3 4 5 7 21 45 49 61
|/~ l
0 1 0 1 1 1 1 1 1
2 0 1 2 1 0 0 1 1
2 3 0 1 3 1 1 1 1
2 3 4 0 2 1 0 4 1
2 3 4 5 0 0 3 0 5
2 3 4 5 7 0 3 7 19
2 3 4 5 7 21 0 4 16
2 3 4 5 7 21 45 0 12
2 3 4 5 7 21 45 49 0
每对倍数在表格中都表示为0
。现在,我们不关心与自身模数相对应的0
(例如2 mod 2, 3 mod 3等等;对角线上的0
),因此我们需要删除它们。一种方法是在其位置上添加1
,如下所示:
=/~ l
1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1
(=/~l) + (|/~l)
1 1 0 1 1 1 1 1 1
2 1 1 2 1 0 0 1 1
2 3 1 1 3 1 1 1 1
2 3 4 1 2 1 0 4 1
2 3 4 5 1 0 3 0 5
2 3 4 5 7 1 3 7 19
2 3 4 5 7 21 1 4 16
2 3 4 5 7 21 45 1 12
2 3 4 5 7 21 45 49 1
这也可以写作(=/~ + |/~) l
。
通过该表格,我们最终得到数字列表:如果某个数字所在的列包含0
,则将其排除。
我们通过对每一列进行乘法运算来建立这个排除列表。如果某一列包含0
,那么它的积就是0
;否则就是一个正数:
*/ (=/~ + |/~) l
256 2187 0 6250 14406 0 0 0 18240
在执行最后一步之前,我们需要稍微改进一下。没有必要进行长时间的乘法计算,因为我们只对 0 和非 0 感兴趣。因此,在构建表格时,我们将通过取每个数字的“符号”(这是
signum
:*
)来保留仅有的 0 和 1:
* (=/~ + |/~) l
1 1 0 1 1 1 1 1 1
1 1 1 1 1 0 0 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1
1 1 1 1 1 0 1 0 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
那么,
*/ * (=/~ + |/~) l
1 1 0 1 1 0 0 0 1
在排除列表中,您只需将数字复制
:#
到您的最终列表中:
l #~ */ * (=/~ + |/~) l
2 3 5 7 61
或者,
(]#~[:*/[:*=/~+|/~) l
2 3 5 7 61