Downcasting double to float: гарантировано ли переполнение?

Если я попробую этот

float f = (float)numeric_limits<double>::infinity();

Или, действительно, попробуйте сделать что-то большее, чем float max вплоть до float, я уверен, что вы закончите бесконечность?

Он работает на GCC, но стандартно ли это?

Ответ 1

float f = (float)numeric_limits<double>::infinity();

Это гарантированно устанавливает f в бесконечность, если ваша платформа компиляции предлагает арифметику IEEE 754 для вычислений с плавающей запятой (обычно это делает).

Или, действительно, попробуйте сделать что-то большее, чем float max вплоть до float, я уверен, что вы закончите бесконечность?

Нет. В режиме ожидания по умолчанию IEEE 754 несколько double значений выше максимального конечного float (т.е. FLT_MAX) преобразуются в FLT_MAX. Точный предел - это число посередине между FLT_MAX (0x1.fffffep127 в шестнадцатеричном представлении C99) и следующий номер float, который может быть представлен, если показатель степени в формате с одной точностью имел больший диапазон 0x2.0p128. Таким образом, предел равен 0x1.ffffffp127 или примерно 3.4028235677973366e + 38 в десятичной форме.

Ответ 2

Из стандарта С++ 11, §4.8.1:

Значение типа с плавающей запятой может быть преобразовано в prvalue другой тип с плавающей точкой. Если исходное значение может быть точно представленный в типе адресата, результатом преобразования является это точное представление. Если значение источника находится между двумя соседними целевые значения, результатом преобразования является определенный реализацией выбор любого из этих значений. В противном случае, поведение undefined.

Отсюда следует, что

  • Если вы бросаете двойную бесконечность в float, вы получаете бесконечную бесконечность.

  • Если вы используете двойное значение, лежащее между float max и бесконечностью, чтобы плавать, вы получаете float max или float бесконечность.