素数を求める(3)
という訳で、最初の実装を高速化してみた。
use strict;
use warnings;
use v5.10;
use Benchmark qw/cmpthese/;
die 'Usage: perl aaa.pl <integer>' if scalar(@ARGV) == 0;
my $max_num = $ARGV[0];
cmpthese( 10, {
'before' => sub {
my @prime = calc_prime1( $max_num );
},
'after' => sub {
my @prime = calc_prime2( $max_num );
}
} );
sub calc_prime1 {
my $n = shift;
my @ret = ();
if ( $n < 2 ) {
return @ret;
}
my @wk = 2..$n;
while ( @wk ) {
my $prime = shift @wk;
@wk = grep { ($_ % $prime); } @wk;
push @ret, $prime;
}
return @ret;
}
sub calc_prime2 {
my $n = shift;
my @ret = ();
if ( $n < 2 ) {
return @ret;
}
my @wk = 0..$n;
$wk[0] = -1;
$wk[1] = -1;
for (my $i=0; $i<=$n; $i++) {
next if $wk[$i] < 0;
my $prime = $wk[$i];
for (my $j=$i+1; $j<=$n; $j++) {
next if $wk[$j] < 0;
if ( ($wk[$j] % $prime) == 0 ) {
$wk[$j] = -1;
}
}
}
return grep { $_ != -1; } @wk;
}
実行結果はこんな感じ。
$ perl aaa.pl 10000
s/iter after before
after 1.82 -- -88%
before 0.218 733% --
うーん、grepしまくりが良くなかったのかなー。
もしくは、pushとか、shiftとか。
ここは憶測で語っても仕方ないので、こんな感じで。
という訳で、これで余りを計算しない方式と比較する準備ができました。
続く。
Leave a Comment