我发现以下代码用Perl编写了关于Eratosthenes的Sieve(一种在给定数字范围内找到素数的算法)并且它工作正常,但我不明白。有人可以为我评论一下,所以我会更好地了解素数是如何找到的吗?
$max= 120;
@primes= ();
@tested= (1);
$j= 1;
while ($j < $max) {
next if $tested[$j++];
push @primes, $j;
for ($k= $j; $k <= $max; $k+=$j) {
$tested[$k-1]= 1;
}
}
print "@primes\n";
答案 0 :(得分:3)
我会像下面那样重写(清理)该脚本,以使其更清晰。
以此为例,如果给变量赋予变量有意义的名称,代码就可以自我记录:
use strict;
use warnings;
my $max = 120;
my @primes;
my @notprime;
for my $num (2..$max) {
next if $notprime[$num];
push @primes, $num;
for (my $multiple = 2 * $num; $multiple <= $max; $multiple += $num) {
$notprime[$multiple] = 1;
}
}
print "@primes\n";
关于Sieve of Eratosthenes
的维基百科文章将完全解释该算法,并提供关于该过程的非常少的视觉效果。但是,摘要就是这样:
答案 1 :(得分:1)
$max= 120;
@primes= ();
$tested
可能会更好地命名为$nonprime
。虽然我们将1
放入数组中,但它实际上并没有做任何有用的事情......它同样可以留空。
此外,@tested
不是非素数列表,而是一个布尔值列表,其索引是非素数。如果出于某种原因,您想将2
标记为非素数,则必须执行以下操作:@tested = (1,1);
@tested= (1);
$j= 1;
扫描1到120之间的所有整数。
while ($j < $max) {
如果我们已经检查了这个数字的原始性并且失败了,请重新启动循环以检查下一个数字。
next if $tested[$j++];
我们现在知道j
是素数,因为我们没有将它标记为非素数,因此我们可以将它添加到列表的末尾。因此,最终列表将按升序排列。
push @primes, $j;
扫描此数组和数组末尾之间的每个剩余数字。我们每次增加新的素数,所以我们基本上跨越了$j
的所有倍数
for ($k= $j; $k <= $max; $k+=$j) {
将每个倍数标记为已测试。我们知道它不能是素数,因为它有$j
作为因素。
$tested[$k-1]= 1;
}
}
脚本的其余部分留给读者练习。
print "@primes\n";