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

Vio*_*ffe 45 c c++ floating-point precision type-conversion

假设条件(int)(i * 1.0f) == i对于任何整数都是正确的是否安全i

Ste*_*non 71

没有.

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

然而,如果i是32位整数,double是IEEE-754双,那么它真实的int(i*1.0) == i.


只是要完全清楚,乘以1.0f 精确的.这是转换intfloat可能不是.

  • 添加到这个答案:简单来说,精度的损失是由于float只有24位来容纳int,因此int有32位,因此在演员表中最低有效位将被舍入. (6认同)
  • @anatolyg:不.在C++中,这由第5节的第10段(*通常的算术转换*)控制:"如果任一操作数是浮点数,另一个操作数应转换为浮点数." 所以`i`在乘法之前转换为`float`,这会导致舍入. (2认同)
  • @MichaelShopsin:除非`a`或`b`是NaN,否则'a <= b`或'a> b`中的一个是真的. (2认同)

thk*_*ala 15

不,对于相同的位宽,IEEE-754浮点数的动态范围比整数的整数精度高.

例如,请参阅此小片段的输出:

int main() {
        int x = 43046721;

        float y = x;

        printf("%d\n", x);
        printf("%f\n", y);
}
Run Code Online (Sandbox Code Playgroud)

43046721无法在32位float数字中提供的24位精度中正确表示,因此输出是这些行的输出:

43046721
43046720.000000
Run Code Online (Sandbox Code Playgroud)

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

一些兴趣点:

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

  • 这不是C的任何独特之处 - 例如Java也受到完全相同的问题.

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