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
Can a conversion from
doubletointbe written in portable C (?)is there any way to implement double_to_int function in cross-platform way (basing only on C standard, even not considering target platforms to support IEEE-754).?
int double_to_int(double val, int *err)
Detail: (int)val truncates the fractional portion, so the range of convertible val using (int)val is mathematically:
INT_MIN - 0.9999... ≤ val ≤ INT_MAX + 0.9999... or
INT_MIN - 1 < val < INT_MAX + 1.
Yes a cross-platform way, by using exact floating-point math and constants, code can test for conversion success.
2.0*(INT_MAX/2+1) is certainly exactly converted to a FP constant.
val - INT_MIN > -1.0 is akin to val > INT_MIN - 1.0 but does not suffer imprecision (with the common 2's complement machines) possible with INT_MIN - 1.0. Recall that the integer type may have greater precision than double. Consider a 64-bit int and INT_MIN - 1.0 not exactly representable as a double.
Code does not use (double)INT_MAX which also may be imprecise.
To copy myself:
#include
#define DBL_INT_MAXP1 (2.0*(INT_MAX/2+1))
#define DBL_INT_MINM1 (2.0*(INT_MIN/2-1))
int double_to_int(double val, int *err) {
if (val < DBL_INT_MAXP1) {
#if -INT_MAX == INT_MIN
// rare non-2's complement machine
if (val > DBL_INT_MINM1) {
*err = OK;
return (int) val;
}
#else
if (val - INT_MIN > -1.0) {
*err = OK;
return (int) val;
}
#endif
// Underflow
*err = ERR_MINUS_INF;
return INT_MIN;
}
if (x > 0) {
// Overflow
*err = ERR_PLUS_INF;
return INT_MAX;
}
// NaN;
*err = ERR_NAN;
return 0;
}
Corner weakness: FLT == 10 and the integer type > 34 bits.