イテレータ修正
やっぱりお馬鹿してたわけで,pushを使えば十分な速さでした.
use strict; use warnings; use Time::HiRes qw/gettimeofday tv_interval/; my $x=primefactory2(); my $sum; my $start = [gettimeofday]; while (1){ my $p=$x->(); last if $p>2000000; $sum += $p; } my $end = [gettimeofday]; printf "%.6f 秒", tv_interval($start, $end); print $sum; sub next_cand{ $_[0] + 2 * ($_[0] % 6 ==5) + 4*($_[0] % 6 ==1); } sub primefactory2{ my @primes=(2,3,5); my $state=-1; return sub{ $state++; return $primes[$state] if $state==0 or $state==1 or $state==2; my $prime_cand=next_cand($primes[-1]); my $th; SIEVE: $th = int(sqrt($prime_cand))+1; foreach my $d ( @primes ){ last if $d>$th; if ( ($prime_cand % $d ==0) ){ $prime_cand = next_cand($prime_cand); goto SIEVE; } } #@primes=(@primes,$prime_cand); push(@primes,$prime_cand); return $primes[-1]; } }
この結果は約12秒でした.