问题
I made a program that returns the sum of all primes under 2 million. I really have no idea what's going on with this one, I get 142891895587 as my answer when the correct answer is 142913828922. It seems like its missing a few primes in there. I'm pretty sure the getPrime function works as it is supposed to. I used it a couple times before and worked correctly than. The code is as follows:
vector<int> getPrimes(int number);
int main()
{
unsigned long int sum = 0;
vector<int> primes = getPrimes(2000000);
for(int i = 0; i < primes.size(); i++)
{
sum += primes[i];
}
cout << sum;
return 0;
}
vector<int> getPrimes(int number)
{
vector<bool> sieve(number+1,false);
vector<int> primes;
sieve[0] = true;
sieve[1] = true;
for(int i = 2; i <= number; i++)
{
if(sieve[i]==false)
{
primes.push_back(i);
unsigned long int temp = i*i;
while(temp <= number)
{
sieve[temp] = true;
temp = temp + i;
}
}
}
return primes;
}
回答1:
The expression i*i
overflows because i
is an int
. It is truncated before being assigned to temp
. To avoid the overflow, cast it: static_cast<unsigned long>( i ) * i
.
Even better, terminate iteration before that condition occurs: for(int i = 2; i*i <= number; i++)
.
Tested fixed.
Incidentally, you're kinda (un)lucky that this doesn't produce extra primes as well as missing some: the int
value is signed, and could be negative upon overflow, and by my reading of §4.7/2, that would cause the inner loop to skip.
回答2:
You may be running into datatype limits: http://en.wikipedia.org/wiki/Long_integer.
回答3:
This line is the problem:
unsigned long int temp = i*i;
回答4:
I'll give you a hint. Take a closer look at the initial value you give to temp
. What's the first value you exclude from sieve
? Are there any other smaller multiples of i
that should also be excluded? What different initial value could you use to make sure all the right numbers get skipped?
There are some techniques you can use to help figure this out yourself. One is to try to get your program working using a lower limit. Instead of 2 million, try, say, 30. It's small enough that you can calculate the correct answer quickly by hand, and even walk through your program on paper one line at a time. That will let you discover where things start to go wrong.
Another option is to use a debugger to walk through your program line-by-line. Debuggers are powerful tools, although they're not always easy to learn.
Instead of using a debugger to trace your program, you could print out messages as your program progressed. Say, have it print out each number in the result of getPrimes
instead of just printing the sum. (That's another reason you'd want to try a lower limit first — to avoid being overwhelmed by the volume of output.)
回答5:
Your platform must have 64-bit longs. This line:
unsigned long int temp = i * i;
does not compute correctly because i is declared int and the multiplication result is also int (32-bit). Force the multiplication to be long:
unsigned long int temp = (unsigned long int) i * i;
On my system, long is 32-bit, so I had to change both temp
and sum
to be unsigned long long
.
来源:https://stackoverflow.com/questions/2800250/sum-of-all-primes-under-2-million