Когда переменная float выходит за пределы поплавка, что происходит?

Я заметил две вещи:

  • std::numeric_limits<float>::max()+(a small number) дает: std::numeric_limits<float>::max().

  • std::numeric_limits<float>::max()+(a large number like: std::numeric_limits<float>::max()/3) дает inf.

Почему это различие? Получает ли 1 или 2 значение OVERFLOW и, следовательно, поведение undefined?

Изменить: Код для тестирования:

1.

float d = std::numeric_limits<float>::max();
float q = d + 100;
cout << "q: " << q << endl;

2.

float d = std::numeric_limits<float>::max();
float q = d + (d/3);
cout << "q: " << q << endl;

Ответ 1

Формально поведение undefined. На машине с IEEE с плавающей точкой, однако, переполнение после округления приведет к в Inf. Однако точность ограничена, и результаты после округления FLT_MAX + 1 FLT_MAX.

Вы можете увидеть тот же эффект со значениями в FLT_MAX. Попробуйте что-то вроде:

float f1 = 1e20;     // less than FLT_MAX
float f2 = f1 + 1.0;
if ( f1 == f2 ) ...

if будет оцениваться как true, по крайней мере, с арифметикой IEEE. (Существуют, или, по крайней мере, существуют машины, где float имеет достаточную точность для if для оценки false, но сегодня они не очень распространены.)

Ответ 2

Это зависит от того, что вы делаете. Если "переполнение" поплавка приходит в выражении, которое возвращается непосредственно, то есть

return std::numeric_limits::max() + std::numeric_limits::max();

операция может не привести к переполнению. Я цитирую из стандарта C [ISO/IEC 9899: 2011]:

Оператор return не является присваиванием. Ограничение перекрытия подпункт 6.5.16.1 не применяется к случаю возврата функции. представление значений с плавающей запятой может иметь более широкий диапазон или точность, чем подразумевается типом; литой можно использовать для удаления этого дополнительный диапазон и точность.

Подробнее см. здесь.