Is it safe to assume that the condition (int)(i * 1.0f) == i
is true for any integer i
?
4 に答える
No.
If i
is sufficiently large that int(float(i)) != i
(assuming float is IEEE-754 single precision, i = 0x1000001
suffices to exhibit this) then this is false, because multiplication by 1.0f
forces a conversion to float
, which changes the value even though the subsequent multiplication does not.
However, if i
is a 32-bit integer and double
is IEEE-754 double, then it is true that int(i*1.0) == i
.
Just to be totally clear, multiplication by 1.0f
is exact. It's the conversion from int
to float
that may not be.
No, IEEE-754 floating point numbers have a greater dynamic range than integers at the cost of integer precision for the same bit width.
See for example the output of this little snippet:
int main() {
int x = 43046721;
float y = x;
printf("%d\n", x);
printf("%f\n", y);
}
43046721
cannot be represented correctly in the 24 bits of precision available in a 32-bit float
number, so the output is something along these lines:
43046721
43046720.000000
In fact, I would expect any odd number above 16,777,216 to have the same issue when converting to a 32-bit float
number.
A few points of interest:
This has more to do with the implicit int-to-float conversion than with the multiplication itself.
This is not by any mean unique to C - for example Java is also subject to the exact same issue.
Most compilers have optimization options that may affect how such conversions are handled, by ignoring certain restrictions of the standard. In such a case,
(int)((float)x * 1.0f) == x
might always betrue
if the compiler optimizes out the conversion tofloat
and back.
No, the behavior is implementation defined because C and C++ don't require IEEE-754, even though that is the most common representation by far.
To be sure that IEEE-754 is used:
- in C, use
#ifdef __STDC_IEC_559__
- in C++, use the
std::numeric_limits<float>::is_iec559
constants
No it is absolutely wrong for all the integers because of the type cast. check code.
#include <stdio.h>
int main()
{
int i = 0;
for (; i < 2147483647; ++i) {
if ((int)(i * 1.0f) != i) {
printf("not equal\n");
break;
}
}
printf("out of the loop\n");
getchar();
return 0;
}
This code assumes that you take 32 bit integer