优化per草中Eratosthenes筛的建议

时间:2014-12-12 01:24:36

标签: perl optimization primes sieve-of-eratosthenes

use warnings;
use strict;

my $in=<STDIN>;
my @array=(1...$in);
foreach my $j(2...sqrt($in)){
        for(my $i=$j*2;$i<=$in;$i+=$j){
            delete($array[$i-1]);
        }
    }

delete($array[0]);
open FILE, ">","I:\\Perl_tests\\primes.dat";

foreach my $i (@array){
    if($i){
        print FILE $i,"\n";
        }
}

我确信有更好的方法来处理所有数字的数组但是我真的不知道在perl中这样做的方法。我对perl很缺乏经验。任何加快它的建议都非常感谢。万分感谢!

2 个答案:

答案 0 :(得分:1)

最快的解决方案是使用模块(例如ntheory),如果你只是想要素数而不关心你是如何得到的。这将大大加快并且使用更少的内存。

我建议查看the RosettaCode Sieve task。显示了许多简单的筛子,快速的字符串版本,一些奇怪的例子,以及几个可扩展的筛子。

即使是基本的内存比你的例子使用更少的内存,并且那里显示的矢量和字符串版本使用的内存要少得多。

除非你是丹·伯恩斯坦,否则阿特金的筛子很少是一种好方法。即使这样,它也比快速SoE实现慢。

答案 1 :(得分:0)

这是寻找素数的一种相当低效的方法,所以除非你绝对必须使用Erastosthenes的Sieve,The Sieve of Atkin可能是一种更快的查找素数的算法。

关于内存使用情况,这里是this python answer的perlified版本。它不是从所有整数的大前沿数组中找出数字,而是跟踪哪些素数是非素数的除数,然后在每次迭代后屏蔽下一个非素数。这意味着您可以生成尽可能多的质数,而无需使用所有RAM,或者不必使用任何内存。更多的代码和更多的间接使得这个版本比你已经的版本慢。

#!/usr/bin/perl

use warnings;
use strict;

sub get() {
    my $this = shift;
    if ($this->{next} == 2) {
        $this->{next} = 3;
        return 2;
    }
    while (1) {
        my $next = $this->{next};
        $this->{next} += 2;
        if (not exists $this->{used}{$next}) {
            $this->{used}{$next * $next} = [$next];
            return $next;
        } else {
            foreach my $x (@{$this->{used}{$next}}) {
                push (@{$this->{used}{$next + $x}}, $x);
            }
            delete $this->{used}{$next};
        }
    }
}

sub buildSieve {
    my $this = {
        "used" => {},
        "next" => 2,
    };
    bless $this;
    return $this;
}

my $sieve = buildSieve();

foreach $_ (1..100) {
    print $sieve->get()."\n";
}

你应该能够将更好的算法与上面更具记忆效率的生成版本结合起来,以提出一个很好的解决方案。

如果您想详细了解算法的工作原理,use Data::Dumper;非常有启发性,并且在每次调用$sieve之间打印get()