0

The number of prime numbers less than 10,000,000 is 664,579 but my code generates only 664,214. The source of the numbers is https://primes.utm.edu/howmany.html

#include <iostream>
#include <bitset>
#include <vector>
using namespace std;

const int N = 10000001;
bitset<N>num;
vector<int>prime;
inline void sieve()
{
    num.flip();
    num[0] = num[1] = 0;
    for(int i=2;i<N;i++)
        if(num[i])
        {
            prime.push_back(i);
            for(long long unsigned j=i*i; j<N;j+=i)
                num[j] = 0;
        }
}

int main() {
    sieve();
    cout << prime.size() << endl;
    return 0;
}
Edward
  • 6,964
  • 2
  • 29
  • 55
MNTahhan
  • 23
  • 5

1 Answers1

4

You have an integer overflow when calculating i*i. The fact that you then assign the result to a long long doesn't make the compiler promote the types before the multiplication.

If I declare i as a long long unsigned int then your program outputs 664579

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
  • 1
    And if the initialisation of `j` is changed to `j=(unsigned long long)i*i`, the correct output is also printed. –  Nov 04 '14 at 12:36
  • And if the limit for the outer loop were set correctly (to sqrt(N)) then the multiplication could never overflow in the first place. That's not only due diligence, it also cuts the number of iterations for the outer loop down to a fraction. Note: depending on rounding mode, `sqrt()` could round up instead of down; better to write a small function `max_factor()` that takes care of the gory details and which can be tested separately. – DarthGizka Nov 04 '14 at 13:27
  • For sieve code in general, the number of boundary cases is greatly reduced if proper data types are used (unsigned int) and even more so if packed (odds-only) bitmaps are used since that buys an extra bit of head room in index variables. Needlessly throwing double-wide integers at a problem is not a strategy that's likely to result in good and robust code; apart from encouraging intellectual laziness it also tends to make code messier instead of better. – DarthGizka Nov 04 '14 at 13:34
  • better check `i <= N/i` before the inner `for` loop is entered. Then `int j` is OK. – Will Ness Nov 05 '14 at 09:00