I need to write function like double_to_int(double val, int *err) which
would covert double val to integer when it\'s possible; otherwise report an error (NAN/I
Yes. (nan/inf handling omitted for brevity)
int convert(double x) {
if (x == INT_MAX) {
return INT_MAX;
} else if (x > INT_MAX) {
err = ERR_OUT_OF_RANGE;
return INT_MAX;
} else if (x == INT_MIN) {
return INT_MIN;
} else if (x < INT_MIN)
err = ERR_OUT_OF_RANGE;
return INT_MIN;
} else {
return x;
}
}
Explanation.
The edge cases, as explained in one of the linked answers, are when INT_MAX is not representable as double exactly, and is rounded up when converted to double, and a symmetric case one with INT_MIN. That's the case when if (x > INT_MAX) fails. That is, the comparison returns false, but we still cannot convert x to int directly.
What the linked answer fails to recognise is that there's only one double number that fails the test, namely (double)INT_MAX, and we can easily catch this case by checking for x == INT_MAX explicitly.
Edit As noted in the comments, this may fail if INT_MAX or INT_MIN is outside of the range of double. While extremely unlikely, this is not precluded by the standard. In such an implementation, the conversion is just (int)x. It should be easier to detect such an implementation at configuration time than at run time. If the latter is absolutely needed, one can perform this operation once:
static int need_simple_conversion = 0;
char* str = malloc(sizeof(int)*CHAR_BIT+1);
sprintf (str, "%d", INT_MAX);
errno = 0;
if (strtod(s, NULL) == HUGE_VAL && errno == ERANGE) {
// INT_MAX overflows double => double can never overflow int
need_simple_conversion = 1;
}
Then
if (need_simple_conversion)
return x;
else { // as above
For the paranoid among us, do this with INT_MIN too and perform the check separately for positive and negative doubles.