3

我,尝试这个简单的代码。它显示了前 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是一个双变量,但我将它设置为(float)i,所以它应该等于 df,但事实并非如此。

例如,数字 16777217 由fdf表示为 16777216 ,但di仍然是 16777217,忽略(float)转换。

这怎么可能?

**我正在使用这个:gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3

4

2 回答 2

2

这篇文章解释了发生了什么:

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

基本上,额外的精度可能会存储在机器上以进行不同的表达式评估,从而使相等的浮点数不相等。

于 2012-03-26T22:51:03.510 回答
2

与您的问题相关的是C99 标准中的 6.3.1.8:2 :

浮动操作数的值和浮动表达式的结果可以用比类型要求更高的精度和范围来表示;类型不会因此而改变。

特别是脚注 52:

仍然需要强制转换和赋值运算符执行它们指定的转换,如 6.3.1.4 和 6.3.1.5 中所述。

阅读脚注,我会说您在编译器中发现了一个错误。

您可能已经在编译器中发现了两个错误:i!=f在浮点数之间进行比较(参见标准同一页上的提升规则),因此它应该始终为 false。尽管在后一种情况下,我认为编译器可能被允许使用更大的类型进行 6.3.1.8:2 的比较,也许使比较等效于(double)i!=(double)f,因此有时为真。第 6.3.1.8:2 段是标准中我最讨厌的一段,我还在努力理解严格的别名。

于 2012-03-26T22:34:09.233 回答