简体   繁体   English

(浮动)铸造不起作用

[英](float) casting does not work

I', trying this simple code. 我正在尝试这个简单的代码。 It shows the first 10 integers that can not be represented in float: 它显示了无法在float中表示的前10个整数:

int main(){
  int i, cont=0;
  float f;
  double di, df;
  for(i=10000000, f=i; i<INT_MAX; i++, f=i, df=f, di=((float)i)){
    if(i!=f){
      printf("i=%d   f=%.2f   df=%.2lf   di=%.2lf\n", i, f, df, di);
      if(cont++==10) return 0;
    }
  }
  return 1;
}

di is a double variable, but I set it to (float)i , so it should be equal to df, but it is not. di是一个双变量,但我把它设置为(float)i ,所以它应该等于df,但事实并非如此。

For example, the number 16777217 is represented as 16777216 by f and df , but di is still 16777217, ignoring the (float) casting. 例如,数字16777217由fdf表示为16777216,但di仍然是16777217,忽略(浮动)转换。

How is this possible? 这怎么可能?

**I am using this: gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3 **我使用的是:gcc(Ubuntu 4.4.3-4ubuntu5)4.4.3

Relevant to your question is 6.3.1.8:2 in the C99 standard : 与您的问题相关的是C99标准中的 6.3.1.8:2:

The values of floating operands and of the results of floating expressions may be represented in greater precision and range than that required by the type; 浮动操作数的值和浮动表达式的结果可以以比该类型所需的精度和范围更高的精度和范围来表示; the types are not changed thereby. 因此不改变类型。

and in particular footnote 52: 特别是脚注52:

The cast and assignment operators are still required to perform their specified conversions as described in 6.3.1.4 and 6.3.1.5. 转换和赋值运算符仍然需要执行6.3.1.4和6.3.1.5中描述的指定转换。

Reading the footnote, I would say that you have identified a bug in your compiler. 阅读脚注,我会说您已经在编译器中发现了一个错误。

You may have identified two bugs in your compiler: the i!=f comparison is done between floats (see promotion rules on the same page of the standard), so it should always be false. 您可能已经在编译器中发现了两个错误: i!=f比较是在浮点数之间完成的(请参阅标准同一页面上的促销规则),因此它应该始终为false。 Although, in this latter case, I think that the compiler may be allowed to use a larger type for the comparison by 6.3.1.8:2, perhaps making the comparison equivalent to (double)i!=(double)f and thus sometimes true. 虽然,在后一种情况下,我认为可以允许编译器使用更大的类型进行6.3.1.8:2的比较,也许使得比较相当于(double)i!=(double)f ,因此有时候是真的。 Paragraph 6.3.1.8:2 is the paragraph in the standard I hate most, and I am still trying to understand strict aliasing. 第6.3.1.8:2段是我最讨厌的标准段落,我仍然试图理解严格的别名。

This post explains what is going on: 这篇文章解释了发生了什么:

http://www.exploringbinary.com/when-floats-dont-behave-like-floats/ http://www.exploringbinary.com/when-floats-dont-behave-like-floats/

Basically extra precision might be stored on the machine for different expression evaluations, making what would be equal floats not equal. 基本上可以在机器上存储额外的精度以用于不同的表达式评估,使得相等的浮点数不相等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM