-1

I wrote an implementation of the Sieve of Atkin in C++ to calculate large primes. It works perfectly fine for finding up to the 10^8th prime, but when trying to find the 10^9th prime number, I get an incorrect result.

It looks like I'm dealing with an integer overflow, but I can't figure out how this is possible. I'm using uint64_t everywhere, and the desired result (22801763489) lies between 2^34 and 2^35.

The result I'm getting is 1326927009.

Here is the relevant code:

uint64_t getPrimesAtkin(uint64_t Nn)
{
    (...)
}


int main(int argc, char** argv) {
    for (int a = 7; a < 10; a += 2)
    {
        clock_t begin = clock();
        uint64_t prime = getPrimesAtkin(pow(10,a));
        clock_t end = clock();
        printf("p(10^%d)=%12d t=%4.3f\n",a,prime, double(end - begin) / CLOCKS_PER_SEC);
    }
}
wvdz
  • 16,251
  • 4
  • 53
  • 90
  • Using floating-point functions (`log()`, `floor()`, etc.) doesn't seem like a terribly good idea. – The Paramagnetic Croissant Jul 19 '15 at 20:04
  • 1
    I don't know C++ so this may be nonsense, but is there a limit on the size of a vector? When you initialize sieve, even though N+1 fits in a uint64_t, perhaps the maximum size of the vector is too small to hold that many booleans. – user448810 Jul 19 '15 at 20:05
  • 2
    `printf("p(10^%d)=%12d...` I don't think `%12d` will make `printf` print a 64 bit integer correctly. Try using `cout`. – Jonathan Potter Jul 19 '15 at 20:05
  • Continuing what @user448810 said, try to ensure 64-bit size_t (meaning vector will support allocating the memory you need) by using appropriate compiler flag. For g++ add `-mcmodel=large` – orip Jul 19 '15 at 20:09
  • @user448810: when using dynamic allocation the max size is dependent on the cpu/compiler/etc. There is no fixed max size for a vector like there is for an array in Java. – wvdz Jul 19 '15 at 20:11

1 Answers1

3

I have not read all of your code carefully, but this line alone can explain your problem:

printf("p(10^%d)=%12d t=%4.3f\n",a,prime, double(end - begin) / CLOCKS_PER_SEC);

Here you pass the 64 bit prime to the printf() function using the format "%12d". This format expects an argument of type int, regardless of the number of digits that are used for output. To print a long long (guaranteed to be at least 64 bits), use the "ll" modifier ("%12lld") and pass the prime with a cast (long long)prime.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106