乘以1.0的精度和浮点转换的int

时间:2012-11-15 15:31:02

标签: c++ c floating-point type-conversion precision

假设条件(int)(i * 1.0f) == i对于任何整数i都为真,是否安全?

4 个答案:

答案 0 :(得分:70)

没有

如果i足够大int(float(i)) != i(假设浮点数是IEEE-754单精度,i = 0x1000001足以表示这一点)那么这是假的,因为乘以{{1}强制转换为1.0f,即使后续乘法没有改变,也会改变值。

但是,如果float是32位整数且i是IEEE-754 double,则 为真double


为了完全清楚,乘以int(i*1.0) == i 的确是。这是从1.0fint的转换,可能不是。

答案 1 :(得分:14)

不,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

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

一些兴趣点:

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

  • 这不是C的任何独特之处 - 例如Java也存在完全相同的问题。

  • 大多数编译器都有优化选项,可能会影响这些转换的处理方式,忽略了标准的某些限制。在这种情况下,如果编译器将转换优化为(int)((float)x * 1.0f) == x并返回,则true可能始终为float

答案 2 :(得分:1)

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

确保使用IEEE-754:

  • 在C中,使用#ifdef __STDC_IEC_559__
  • 在C ++中,使用std::numeric_limits<float>::is_iec559常量

答案 3 :(得分:-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位整数