SPUG: Sophistry Re: Primes

Fred Morris m3047 at inwa.net
Sat Oct 6 17:16:23 PDT 2007


Eratosthenes clearly calls out the procedure for his Sieve and you have to 
allocate the entire range and then you mark them off... yes/no, yes/no...

Here, the limit could be dynamic: the algorithm consumes the resources it 
needs, when it needs them. The Sieve, while it may be conceptually posited as 
a story to understand what is going on here, never exists at one point in 
space/time: you might see it with appropriate time-lapse photography. In 
reality though the holes appear as we learn something about them and 
disappear as we pass them.

In the case of the actual Sieve, the "holes" are dumb. Here the "holes" tell 
you their factors.

Notwithstanding the foregoing, an important observation which applies to 
Sieves does apply here.

1) When we find a prime P, the first hole we need to tell about it is P 
squared. This means that the holes no longer have a complete list of (prime) 
factors as it did in the naive version, but a hole H still contains a list of 
all factors <= sqrt(H), which is sufficient to compute the complete list of 
factors with little difficulty.

2) The limit still can be utilized as a hint for some optimizations. Once we 
get past the square root of the limit, a prime is still a prime but we don't 
need to post it forward because it's past the limit.

(Here, without the subroutine... although I still feel more comfortable making 
sure something exists before I attempt to do something with it.)

(Why the map in void context? A Pythonism or something, I guess.)

(Is this the best way to find primes? Wot, you're gonna use Perl to find 
primes?)

#!/usr/bin/perl

use Getopt::Std;
use vars qw/ %Options /;
use strict;
#use warnings;

getopts('p:t', \%Options );

my $limit = $Options{p};
($limit =~ m/^\d+$/) or die 'p must be an unsigned decimal integer';
my $truncate = exists $Options{t} ? sqrt($limit) : $limit;

my $i = 2; # First possible value.
my %numbers;

while ($i < $limit) {

    if (exists $numbers{$i}) {
        map push( @{$numbers{$i+$_}},$_), @{$numbers{$i}};
        delete $numbers{$i};
    }
    else {
        printf "%8d\n", $i;
        push( @{$numbers{$i*$i}},$i) if ($i < $truncate);
    }

    $i += 1;
}

exit(0);

__END__

Fred Morris



More information about the spug-list mailing list