Когда преобразование целого числа в плавающее выполняется без потерь?
Когда тип с плавающей запятой имеет достаточную точность и диапазон для кодирования всех возможных значений целочисленного типа.
Всегда ли следующий код int32_t
возвращает истину? -> Да. Всегда ли следующий код int64_t
возвращает истину? -> Нет.
Так как DBL_MAX
не меньше 1E + 37, то диапазон достаточен как минимум для int122_t
, давайте посмотрим на точность.
С обычным double
, с его основанием 2, знаковым битом, 53-битным значащим и показателем, все значения int54_t
с его 53 битами значений могут быть представлены точно. INT54_MIN
также можно представить. С этим double
он имеет DBL_MANT_DIG == 53
и в данном случае это количество цифр с основанием 2 в мантиссе с плавающей запятой.
Наименьшее непредставимое значение величины будет INT54_MAX + 2
. Тип int55_t
и шире имеет значения, которые нельзя точно представить как double
.
Для типов uintN_t
имеется еще 1 бит значения. Типичный double
может затем кодировать все uint53_t
и более узкие.
С другими возможными кодировками double
, поскольку C указывает DBL_DIG >= 10
, все значения int34_t
могут проходить туда и обратно.
Код всегда истинен с int32_t
, независимо от double
кодировка.
Что означает int64_t
?
UB-потенциал с int64_t
.
Преобразование в int64_t i ... double d = i;
, если оно неточно, соответствует определенной реализации результат 2-х ближайших кандидатов. Часто это округление от до ближайшего . Тогда i
значения около INT64_MAX
могут преобразоваться в double
на единицу больше, чем INT64_MAX
.
С int64_t i2 = d;
, преобразование значения double
на единицу больше INT64_MAX
в int64_t
- это неопределенное поведение (UB).
Простой предварительный тест для обнаружения этого:
#define INT64_MAX_P1 ((INT64_MAX/2 + 1) * 2.0)
if (d == INT64_MAX_P1) return false; // not lossless