You are not logged in.
I'm using strtod() in an RPN implementation, and I'm working on input validation. As per strtod(3), I've written the following conditional to catch input overflow.
...
errno = 0;
op1 = strtod(token, &endPtr);
if ((errno == ERANGE && (op1 == HUGE_VALF || op1 == HUGE_VALL)) || (errno != 0 && op1 == 0)) {
printf("Error: Input overflow.\n");
clearstack();
return 1;
}
...
Except that when I enter something that would definitely overflow, this conditional is never entered. Furthermore, errno is never set. What am I missing?
A link to the full code can be found here
Last edited by falconindy (2010-04-13 17:49:15)
Offline
Well the first wrong thing I see is that you should really test if fabs(op1) is HUGE_VAL{F,L}.
The second thing is, why so complicated a test? errno != 0 should be all you need.
The third thing is, if errno is really not being set, are you sure you're really overflowing? doubles go up to about 1.8e308 on most arches.
Offline
Here is a little program I wrote to test this, and it seems to work:
$ cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
int main ()
{
char *input = NULL, *end = NULL;
size_t input_len = 0;
double output = 0.0;
if (getline (&input, &input_len, stdin) != -1) {
errno = 0;
end = input + input_len;
output = strtod (input, &end);
if (errno == ERANGE) {
if (fabs (output) == 0) {
printf ("Underflow occured\n");
} else if (fabs (output) == HUGE_VAL) {
printf ("Overflow occured\n");
}
} else {
printf ("%e\n", output);
}
}
free (input);
return 0;
}
$ perl -e 'print (1..100)' | ./a.out
1.234568e+191
$ perl -e 'print (1..1000)' | ./a.out
Overflow occured
Hope this is helpful.
Offline
Well the first wrong thing I see is that you should really test if fabs(op1) is HUGE_VAL{F,L}.
The second thing is, why so complicated a test? errno != 0 should be all you need.
Fair enough. This is the first time I'm really dealing with floating point ops in C.
The third thing is, if errno is really not being set, are you sure you're really overflowing? doubles go up to about
1.8e308 on most arches.
Huh... wouldn't an unsigned double be, at most, 2^128 - 1 and more likely 2^64 - 1? I'm dealing with signed, so its then half that. Sure enough, sizeof(double) returns 8.
Also, this is what made me think I'm hitting overflow.
> 111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1 *
= 111111111111111105547424803279259724863245197668615715838829352563602489955831513088.000
>
Hmm. If I go even further, I eventually do hit an overflow error. However, that still leaves me a little baffled as to the results above. Is this a result of the decimal precision inherent in a double?
Offline
A double works a bit different. It stores a mantissa (15-16 digits for a double, iirc) and an exponent, similar to the scientific notation of 0.123456*e^100. (Wiki for more info: http://en.wikipedia.org/wiki/IEEE_754-1985)
So these are two separate issues:
1. Overflow of the exponent -> you have a number bigger than 10^308 (* some constant, which I don't remember)
2. Loss of precision, because you can only store 15-16 digits.
Offline
A double works a bit different. It stores a mantissa (15-16 digits for a double, iirc) and an exponent, similar to the scientific notation of 0.123456*e^100. (Wiki for more info: http://en.wikipedia.org/wiki/IEEE_754-1985)
So these are two separate issues:
1. Overflow of the exponent -> you have a number bigger than 10^308 (* some constant, which I don't remember)
2. Loss of precision, because you can only store 15-16 digits.
Got it. Thanks for the link. I think I know where to dig, now.
Offline