I am a sort of newbie to programming (actually coming back to it after a gap of 20 yrs :) ). I am trying to make a program for a question on project euler, to find sum of all prime numbers under 2 million. I am trying to use the Eratosthenes sieve algorithm. I am using code::blocks with GNU GCC compiler.
#include <stdio.h>
#define L 2000000
int main()
{
unsigned long long int i, j, n, num[L], sum = 0;
for (i = 0; i < L; i++)
num[i] = i + 1;
for (j = 2; j*j <=L; j++)
{
for (n = j; n*j<=L; n++)
{
num[n * j - 1] = 0;
}
}
for (i = 1; i < L; i++)
{
if (num[i] != 0)
{
printf("%llu\n",num[i]);
sum = sum + num[i];
}
}
printf("%llu\n", sum);
return 0;
}
The program works for all values of L below 1000000, but stops working above that. Also I get warning about the long long int as follows:
***||=== Build file: Debug in 2MILLIONPRIMESUM (compiler: GNU GCC Compiler) ===|
***E:\Code Blocks Projects\2MILLIONPRIMESUM\main.c||In function 'main':|
E:\Code Blocks Projects\2MILLIONPRIMESUM\main.c|22|warning: unknown conversion type character 'l' in format [-Wformat=]|
E:\Code Blocks Projects\2MILLIONPRIMESUM\main.c|22|warning: too many arguments for format [-Wformat-extra-args]|******
I get similar warnings when trying to use "long double" etc. Is this a problem with the compiler, that it cannot handle long long and long double?
The above code works without any warning (only for L <=1000000) on GDB online compiler. Request everyone to advise me on the above issues. Thank you so much in advance.
As pointed out in comments,
2000000 * sizeof(long long)is too large of an array to fit on the stack; confidence is high that this is the root cause of the issue.That said, the code works nicely when we add the dynamic memory allocation of
numas shown below in the line havingmalloc(). We also added code to ensure the memory allocation was successful. If not, aprintf()is there to alert the user, and then the program exits harmlessly.This code was compiled and run/checked by me before posting.
EDIT: I ran one more test just now with
sumas typedouble-- the final answer is still the same:142913828922. This tends to support the notion that the code is working per design and requirement.Output:
This 2nd version may interest you: per discussion with Fe2O3 in comments, it was revealed that the
numarray need not occupy along longdata type; that the range ofnumarray will fit neatly into a 32-bit int.Furthermore, upon reflection, it was realized that such a change invites a considerable space savings. So much so that perhaps the adapted
numarray may now fit on the stack!This notion seems to be born out per the runnable code here.
Conspicuously absent from the code is any hint of
malloc(), and yet we're getting competent results per the featuredOutput:Output:
Nice thing about Stackverflow community is that they'll bring ideas to the table that challenge and grow you. Both Fe2O3 and Jonathan Leffler mentioned using bits for even more space savings. (Wut?) At last I've worked it out...
Here is version 3.0 for the world -- only puts about 240K on the stack -- nice! That's a long way from the 2 terrabytes we started with. (j/k -- was actually 2M * 64bits = 15.25MB)
Runnable code is here.
Output:
Here is version 4.0 -- only puts about 122K on the stack.
The bit array is halved since v3.0. Thanks again to the SO community for the inspiration -- please see comments for more, and the algo optimizations from Fe2O3.
Runnable code is here.
Output:
My 2 cents for version 5.0:
L, defaults to2000000unsigned longfor all computationsbitsarray now allocated and initialized to0, indicates composite numbersChqrlie.
Output (13ms total time):