I wrote this code to find the xth greatest prime numbers:
for (int i = 3 /* 2 has already been added to the list */; i < maxNumber; i += 2) {
for (int tested = 0; ; tested++) {
if (primes[tested] == 0) {
break;
}
if (i % (int) primes[tested] == 0) {
goto loop;
}
}
count++;
if (count == primesSize) {
primesSize += 2000;
primes = (double*) realloc(primes, sizeof(double) * primesSize);
}
primes[count - 1] = i;
printf("Prime number #%d: %d\n", count, i);
printf("Prime size: %d\n", primesSize);
loop: /* statement that does nothing */ if (1) {}
}
However it returned a "Floating point exception" when using big numbers (> 8,000).
When happens here:
maxNumber
is set to the square root of the chosen number.1000 * sizeof(double)
is allocated. It is stored in the primes
variable.primes
pointer is reallocated to store 2,000 more numbers.When I used gdb
to find out the cause of the error, I found that this part was the cause of problem:
for (int tested = 0; ; tested++) {
if (primes[tested] == 0) {
break;
}
if (i % (int) primes[tested] == 0 /* breaks here */) {
goto loop;
}
}
Update: I thought the first if
statement would catch that issue, because printf("%f", primes[tested])
prints 0. However, it doesn't and the "break" is not executed.
When the code broke, tested
was 1001. I convert primes[tested]
to an integer because the modulo arithmetic operation I use requires ints to work. However, when I print primes[tested]
from code it shows 0. If I print the value from gdb, I get 6.1501785659964211e-319.
What am I missing? Should I modify my call to realloc
to avoid this exception?
I thought the first
if
statement would catch that issue, becauseprintf("%f", primes[tested])
prints 0. However, it doesn't and the "break" is not executed.
You test whether primes[tested] == 0
, but your code is only valid if ((int)primes[tested]) == 0
. These are not at all the same thing. Moreover, printing the value of primes[tested]
with format %f
does not reliably tell you differently, because it gives you only 6 digits after the decimal point. Try a "%e"
format instead, and test the condition you actually require, not a related, weaker one.
But even better, don't use a floating-point type here. FP has no business being used in a discrete math problem, such as you appear to be trying to solve. If primes[tested]
in fact holds prime or possibly-prime numbers then unsigned long long int
likely has the same size as double
, and almost surely can exactly represent a wider range of primes. Or if it just contains flags, such as in a prime number sieve, then anything wider than char
is wasteful.