Информация об изменениях

Сообщение Re[3]: сконвертировать unsigned int в float без потери точно от 02.12.2015 16:52

Изменено 02.12.2015 16:56 watchmaker

Здравствуйте, B0FEE664, Вы писали:


BFE>Из вашего комментария я понимаю, что этот интервал определяется размером мантиссы, т.е. assert должен быть таким:


BFE>assert(n <= (1U << FLT_MANT_DIG) — 1);


BFE>Верно?


Нет, если FLT_MANT_DIG = 24 и FLT_RADIX = 2, то такое условие сводится к assert(n ≤ 16777215). То есть число 16777216 не удовлетворяет ему, хотя оно и точно представимо в IEEE754-float, и непосредственно прилегает к отрезку [0, 16777215] — то есть этот отрезок может быть увеличен.

А так практически всё верно.

Но, конечно, формально это не переносимо. FLT_RADIX не всегда равен 2. А в мантиссе не всегда присутствует неявный старший бит.
Если же исправить ошибку с числом 16777216, и добавить проверку
static_assert(std::numeric_limits<float>::is_iec559, "IEEE 754 floating point");
то будет вполне надёжно.
Re[3]: сконвертировать unsigned int в float без потери точно
Здравствуйте, B0FEE664, Вы писали:


BFE>Из вашего комментария я понимаю, что этот интервал определяется размером мантиссы, т.е. assert должен быть таким:


BFE>assert(n <= (1U << FLT_MANT_DIG) — 1);


BFE>Верно?


Нет, не учтено разложение на произведение чётного и нечётного чисел. Так если FLT_MANT_DIG = 24 и FLT_RADIX = 2, то твоё условие сводится к assert(n ≤ 16777215). То есть число 16777216 не удовлетворяет ему, хотя оно и точно представимо в IEEE754-float, и непосредственно прилегает к отрезку [0, 16777215] — то есть этот отрезок на самом деле может быть увеличен.

В остальном практически всё верно.

Но формально это не переносимо. FLT_RADIX не всегда равен 2. А в мантиссе не всегда присутствует неявный старший бит.
Если же исправить ошибку с числом 16777216, и добавить проверку
static_assert(std::numeric_limits<float>::is_iec559, "IEEE 754 floating point");
то будет вполне надёжно.