(плавать) литье не работает - PullRequest
3 голосов
/ 27 марта 2012

Я, пробую этот простой код.Он показывает первые 10 целых чисел, которые не могут быть представлены в float:

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 представлено как 16777216 как f и df , но di по-прежнему 16777217, игнорируя (float) casting.

Как это возможно?

** Я использую это: gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Ответы [ 2 ]

2 голосов
/ 27 марта 2012

Этот пост объясняет, что происходит:

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

Как правило, дополнительная точность может храниться на машине для различных вычислений выражений, делая то, что будет равно, с плавающей точкой не равно.

2 голосов
/ 27 марта 2012

Отвечает на ваш вопрос 6.3.1.8:2 в стандарт C99 :

Значения плавающих операндов и результатов плавающих выражения могут быть представлены с большей точностью и дальностью, чем что требуется по типу; типы не меняются.

и, в частности, сноска 52:

Операторы приведения и присваивания все еще должны выполнять свои указанные преобразования, как описано в 6.3.1.4 и 6.3.1.5.

Читая сноску, я бы сказал, что вы обнаружили ошибку в вашем компиляторе.

Возможно, в вашем компиляторе обнаружены две ошибки: i!=f сравнение выполняется между поплавками (см. Правила продвижения на одной странице стандарта), поэтому оно всегда должно быть ложным. Хотя в этом последнем случае я думаю, что компилятору может быть разрешено использовать больший тип для сравнения на 6.3.1.8:2, возможно, делая сравнение эквивалентным (double)i!=(double)f и, следовательно, иногда истинным. Пункт 6.3.1.8:2 - это абзац в стандарте, который я больше всего ненавижу, и я все еще пытаюсь понять строгий псевдоним.

...