Reputation: 11
We have a coding homework related to prime and my friend wrote this code. Its long and I dont understand it that much and has goto
which is I think frowned upon so I don't know. Can help decide if we should we keep it?
int getNth (int nth){
vector<int> prime;
int sievelmt = nth*10;
int i,j;
func:
vector<int> sieve(sievelmt, -1);
prime.push_back(2); if (nth == 1) return 2;
prime.push_back(3); if (nth == 2) return 3;
prime.push_back(5); if (nth == 3) return 5;
for (i = 2; i <= sievelmt; i++)
{
if (i%2==0||i%3==0||i%5==0) continue;
if (sieve[i] == -1)
{
prime.push_back(i); if (prime.size()==nth) return prime[prime.size()-1];
for ( j = 1; i*j <= sievelmt; j++) sieve[i*j]=j;
}
else continue;
}
sievelmt *= 10;
sieve.clear(); prime.clear();
goto func;
return -1;
}
Upvotes: 1
Views: 85
Reputation: 36441
The heart of the algorithm is this line:
for ( j = 1; i*j <= sievelmt; j++) sieve[i*j]=j;
For a given i
that fills locations of array sieve
that are multiples of i
, with the rank of the multiple. Imagine i=7
, then sieve[7]=1
, sieve[14]=2
, sieve[21]=3
, etc.
This is the base of Eratosthène's sieve, a very very old algorithm (Eratosthène was an ancient Greek scientist) to find primes. If you make i
vary from 2 to some value, then this will mark every location whose index is not prime. At the end, every location not marked is then a prime. Let see:
i=2
.1.2.3.4.5.6.7.
i=3
.112.2.435.4.75
, 3 is prime (first time location 3 has been visited)i=4
.111.2.235.3.75
i=5
.11112.232.3.73
, 5 is prime (first time location 5 has been visited)i=6
.11111.232.3.73
i=7
.111111232.3.23
, 7 is primei=8
.111111132.3.23
i=9
.111111112.3.23
i=10
.111111111.3.23
i=11
.11111111113.23
, 11 is primeWhy is there a goto
here? Don't worry, there exists numerous dangerous usage of goto
, but that one is not. If you don't feel ok with that one replace:
func:
...
goto func;
with:
while(1) {
...
}
So the real question is why there is some "infinite" loop other there?
This is because you are looking for the n-th prime, but you can't easily determine how long the array must be to be able to capture the n-th prime... So that implementation just tries with increasing sizes. The first time, algorithm hopes that the n-th prime will be in an array of size 10*n, if it is not sufficient, then the size is mutiplied by 10, again, and again, until the n-th prime will be in.
Could I optimize this?
Sure, there is some little tricks. First you can see that if a given i
it is divisible by 2, 3 or 5, then it can't be prime. That has already been implemented:
if (i%2==0||i%3==0||i%5==0) continue;
Then you may say, ok if divisible by 7 or 11 or 13, etc (means by any other prime), it's the same! I will not tell you more, but of course you can transform that algorithm to determine if a given i
is or not divisible by any prime less then i
(maybe by storing slightly different values in the array).
Upvotes: 1