45

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

4

4 回答 4

72

不。

如果i足够大int(float(i)) != i(假设 float 是 IEEE-754 单精度,i = 0x1000001足以证明这一点)那么这是错误的,因为乘以1.0f强制转换为float,即使随后的乘法不会改变值。

但是,如果i是 32 位整数并且IEEE-754 双精度,double那么.int(i*1.0) == i


为了完全清楚,乘法1.0f 准确的。可能不是从int到的转换。float

于 2012-11-15T15:34:27.763 回答
15

不,IEEE-754浮点数具有比整数更大的动态范围,但以相同位宽的整数精度为代价。

例如看这个小片段的输出:

int main() {
        int x = 43046721;

        float y = x;

        printf("%d\n", x);
        printf("%f\n", y);
}

43046721无法以 32 位float数字中可用的 24 位精度正确表示,因此输出如下所示:

43046721
43046720.000000

事实上,我希望任何高于 16,777,216 的奇数在转换为 32 位float数字时都会出现同样的问题。

几个兴趣点:

  • 这与隐式 int-to-float 转换有关,而不是与乘法本身有关。

  • 这绝不是 C 独有的——例如 Java 也遇到完全相同的问题。

  • 大多数编译器都有优化选项,通过忽略标准的某些限制,可能会影响处理此类转换的方式。在这种情况下,如果编译器优化了来回转换,则(int)((float)x * 1.0f) == x可能总是如此。truefloat

于 2012-11-15T15:45:14.047 回答
1

不,行为是实现定义的,因为 C 和 C++ 不需要 IEEE-754,尽管这是迄今为止最常见的表示。

为确保使用 IEEE-754:

  • 在 C 中,使用#ifdef __STDC_IEC_559__
  • 在 C++ 中,使用std::numeric_limits<float>::is_iec559常量
于 2015-06-15T15:31:23.643 回答
-5

不,由于类型转换,所有整数都是绝对错误的。检查代码。

#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;
}

此代码假定您采用 32 位整数

于 2012-11-15T15:40:39.453 回答