Precision of multiplication by 1.0 and int to float conversion

后端 未结 4 1050
一个人的身影
一个人的身影 2020-12-16 08:53

Is it safe to assume that the condition (int)(i * 1.0f) == i is true for any integer i?

相关标签:
4条回答
  • 2020-12-16 09:36

    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.

    0 讨论(0)
  • 2020-12-16 09:51

    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
    0 讨论(0)
  • 2020-12-16 09:51

    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

    0 讨论(0)
  • 2020-12-16 09:54

    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 be true if the compiler optimizes out the conversion to float and back.

    0 讨论(0)
提交回复
热议问题