Summing Prime Numbers below two million
You may have heard of a website called Project Euler (projecteuler.net). I'm working through the first problems, which were quite trivial, and I'm on the problem described in the title.
This isn't about optimising or anything - it takes about 90 thousandths of a second to complete. It's giving me the wrong total.
Can someone help me? I have no clue why the answer I'm getting - from both the array total (atotal) and the total that was added up normally (total) - is incorrect. The answer they are both showing is 947402457, which the website it telling me is the wrong answer.
In case it's just the wording, the question is here: http://projecteuler.net/index.php?section=problems&id=10
What's also very strange is, as far as I can tell, when, at the end when you can type in which prime number you would like to view (it takes it out of the array), it gives you the correct answer.
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <ctime>
typedef unsigned long int bignum;
//there are 666671 primes below two million
int main(){
using namespace std;
bignum top = 2000000;
bignum total = 0;
bignum atotal = 0;
//hardcode 2 and 3
total += 5;
int inc = 2;
bignum n = 5;
double sq = n;
bignum np = 1;
bignum *pa = new bignum[top];
pa[0] = 2;
pa[1] = 3;
while (n < top){
int div = 5;
int divinc = 2;
int p = 1;
//check if number is prime
//check divisiblity from any possible prime up to the square root of n
//first hardcode 2 and 3
if(n%2==0||n%3==0)
p = 0;
else{
while(div<=sqrt(sq)){
if(n%div==0){
p = 0;
break;
}else{
div = div + divinc;
if(divinc==2) divinc = 4; else divinc = 2;
}
}if(p!=0){ //if it's a prime - 0 is not, 1 is prime
total = total + n;
np++;
pa[np] = n;
//cout << np << " prime number: " << n << endl; //takes too long if it prints everything
}
}
n += inc;
if(inc==2) inc = 4; else inc = 2;
}
for (int c=0;c<=np;c++){
atotal += pa[c];
}
cout << "Total " << top << ": " << total << endl;
cout << "Array total: " << atotal << endl;
cout << "Elapsed time: " << clock() << " " << CLOCKS_PER_SEC << "s of a second" << endl << endl;
while(true){
int ptoview = 0;
cout << "Enter the number of the prime you would 开发者_JS百科like to see (you can view every prime number below "<<top<<") ";
cin >> ptoview;
if (pa[ptoview-1]){
if (pa[ptoview-1] < top)
cout << ptoview << " prime: " << pa[ptoview-1] << endl;
else
cout << "Too high/low" << endl;
cout << endl;
}
}
system("PAUSE");
return 0;
}
Here's a clue to at least one problem. Have a look at what happens when you replace:
for (int c=0;c<=np;c++){
atotal += pa[c];
}
with:
for (int c=0;c<=np;c++){
bignum oldatotal = atotal;
atotal += pa[c];
if (atotal < oldatotal)
cout << "Hmmm: " << oldatotal << " " << atotal << endl;
}
I get something like:
Hmmm: 4294819625 12858
Hmmm: 4294864122 123849
Hmmm: 4294717053 27802
Hmmm: 4294697657 51420
: : :
Hmmm: 4293781002 792849
Hmmm: 4294658253 1676602
Hmmm: 4293686116 710941
Hmmm: 4294706293 1737578
Total 2000000: 947402457
Array total: 947402457
I won't go into the detail since this is a puzzle and I'm assuming you want to keep it at least a little challenging :-)
And yes, you're right (based on your comment below) so I'll make the answer a little less obtuse so it's more useful for others.
The unsigned long
type is not big enough to hold the sum of all those primes so it's wrapping around.
Whether it can hold the actual primes themselves I haven't checked, but the answer in the next paragraph will solve that as well.
You might want to try redefining bignum
as a "larger" type like unsigned long long
if available.
Not looked at everything but sq
isn't modified in the main while loop. That doesn't seem right. (BTW, I'd have used a sieve filter to get to the primes).
精彩评论