Before this afternoon, I thought that a check like this for a double 'd':
d == floor (d) && d >= LONG_MIN && d <= LONG_MAX
was sufficient to determine whether converting 'd' to 'long' would
yield a 'long' with the same value as 'd'.
Now I realize that this is wrong. In particular, take a look at the
following program:
#include <limits.h>
#include <stdio.h>
int main (void)
{
long i = LONG_MAX;
double d = i;
long j = d;
printf ("%ld, %f, %ld\n", i, d, j);
return 0;
}
On my system, this prints:
9223372036854775807, 9223372036854775808.000000, -9223372036854775808
In other words, LONG_MAX gets rounded up to 2**63 when it's converted to
'double', which makes sense because 'double' only has 53 bits of precision,
but this also means that 'd <= LONG_MAX' and still doesn't fit in 'long', as one
can see from it getting converted to a wrong answer (-2**63 instead of
2**63) when converted back to 'long'. And of course any answer is OK there,
since this out-of-range conversion yields undefined behavior.
Can anyone suggest a correct way to check whether a 'double' is in the
range of 'long'?
One workaround would be to check for the range of 'int' (or int32_t, I guess
really), since there's not going to be any loss of precision converting
INT(32)_MAX to 'double'. But I'd rather support a wider range in the code
I'm working on.
Thanks,
Ben.