So, everything seems to be working nicely, but the program doesn't give me the correct answer. Mine is 142,915,960,832, whereas it should be 142,913,828,922. The differece is 2,131,910 (if I still can subtract numbers on paper haha) and I have no idea where did I get those two millions. Could anyone help me?
#include <stdio.h>
#include <math.h>
#define BELOW 2000000
int isaprime (int num);
int main (void) {
int i;
float sum = 0;
for (i = 2; i < BELOW; i++) {
if (isaprime(i) == 1) {
sum = sum + i;
printf ("\n%d\t%.1f", i, sum);
}
}
getch();
return 0;
}
int isaprime (int num) {
int i;
for (i = 2; i <= sqrt(num); i++) {
if (num % i == 0) {
return 0;
}
else {
;
}
}
return 1;
}
Using float
as the sum
is the problem. The largest integer k
such that all integers from [-k, k]
are exactly representable in 32-bit float is 2^241; after that you will start losing precision in some integers. Since your sum is outside that range that, by an absurd margin, you lose precision and all bets are off.
You need to change to a larger type like long
(assuming it's 64-bits on your machine). Make the change, and you'll get right answer (as I did with you code):
[ec2-user@ip-10-196-190-10 ~]$ cat -n euler.c
1 #include <stdio.h>
2 #include <math.h>
3
4 #define BELOW 2000000
5
6 int isaprime (int num);
7
8 int main (void) {
9
10 int i;
11 long sum = 0;
12
13 for (i = 2; i < BELOW; i++) {
14
15 if (isaprime(i) == 1) {
16 sum = sum + i;
17 }
18 }
19 printf("sum: %ld\n", sum);
20
21 return 0;
22 }
23
24 int isaprime (int num) {
25
26 int i;
27
28 for (i = 2; i <= sqrt(num); i++) {
29 if (num % i == 0) {
30 return 0;
31 }
32 else {
33 ;
34 }
35 }
36
37 return 1;
38 }
[ec2-user@ip-10-196-190-10 ~]$ gcc euler.c -lm
[ec2-user@ip-10-196-190-10 ~]$ ./a.out
sum: 142913828922
1: 23 explicit bits in the mantissa plus one hidden bit.
As @LeeDanielCrocker suggested, here is an implementation of the Sieve of Eratosthenes that solves the problem instantaneously:
#include <stdio.h>
#include <string.h>
#define ISBITSET(x, i) (( x[i>>3] & (1<<(i&7)) ) != 0)
#define SETBIT(x, i) x[i>>3] |= (1<<(i&7));
#define CLEARBIT(x, i) x[i>>3] &= (1<<(i&7)) ^ 0xFF;
long long sumPrimes(int n) {
char b[n/8+1];
long long i, p;
long long s = 0;
memset(b, 255, sizeof(b));
for (p=2; p<n; p++) {
if (ISBITSET(b,p)) {
//printf("%d\n", p);
s += p;
for (i=p*p; i<n; i+=p) {
CLEARBIT(b, i); }}}
return s; }
int main(void) {
printf("%lld\n", sumPrimes(2000000));
return 0; }
At ideone, that returns in thirty milliseconds. The optimized version shown below, which sieves only on odd numbers and handles 2 separately, runs in zero time (less than ten milliseconds) at ideone.
#include <stdio.h>
#include <string.h>
#define ISBITSET(x, i) (( x[i>>3] & (1<<(i&7)) ) != 0)
#define SETBIT(x, i) x[i>>3] |= (1<<(i&7));
#define CLEARBIT(x, i) x[i>>3] &= (1<<(i&7)) ^ 0xFF;
long long sumPrimes(int n) {
int m = (n-1) / 2;
char b[m/8+1];
int i = 0;
int p = 3;
long long s = 2;
int j;
memset(b, 255, sizeof(b));
while (p*p < n) {
if (ISBITSET(b,i)) {
s += p;
j = (p*p - 3) / 2;
while (j < m) {
CLEARBIT(b, j);
j += p; } }
i += 1; p += 2; }
while (i < m) {
if (ISBITSET(b,i)) {
s += p; }
i += 1; p += 2; }
return s; }
int main(void) {
printf("%lld\n", sumPrimes(2000000));
return 0; }
If you're interested in programming with prime numbers, I modestly recommend this essay at my blog; it describes both algorithms given above, covers all the algorithms you will need to solve the prime-number problems at Project Euler, and includes source code in C and four other languages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With