素数を求める(4)

次は、2つの方式の速度比較。

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, {
    'calc1' => sub {
        my @prime = calc_prime1( $max_num );
    },
    'calc2' => sub {
        my @prime = calc_prime2( $max_num );
    }
} );

sub calc_prime1 {
    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;
}

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;

        for (my $j=($i+$i); $j<=$n; $j+=$i) {
            $wk[$j] = -1;
        }
    }

    return grep { $_ != -1; } @wk;
}

実行結果はこんな感じ。

$ perl aaa.pl 10000
            (warning: too few iterations for a reliable count)
        s/iter  calc1  calc2
calc1     1.89     --   -99%
calc2 1.00e-02 18760%     --

分かってはいたんですけどね、体感で違い過ぎたので。
ただ、添え字でどうこうするのは、
大きな素数を計算するのには向かない気がするので、
その場合は時間が掛かってでも、
すでに見つかった素数で余りを計算する方が現実的な気がします。
でも、そこはSSDを使えば、もっと早く計算できたりするんですかね。

という訳で、素数の計算はここまで。

おしまい。

Leave a Comment