Можно ли считать, что условие (int)(i * 1.0f) == i
истинно для любого целого числа i
?
Точность умножения на 1.0 и int для плавающего преобразования
Ответ 1
Нет.
Если i
достаточно велико, чтобы int(float(i)) != i
(предполагая, что float является одиночной точностью IEEE-754, для этого достаточно i = 0x1000001
), то это неверно, потому что умножение на 1.0f
заставляет преобразовать в float
, который изменяет значение, даже если последующее умножение не делает.
Однако, если i
является 32-разрядным целым числом, а double
является IEEE-754 double, то верно, что int(i*1.0) == i
.
Чтобы быть абсолютно ясным, умножение на 1.0f
является точным. Это преобразование из int
в float
, которое может не быть.
Ответ 2
Нет, IEEE-754 числа с плавающей запятой имеют больший динамический диапазон, чем целые, за счет целочисленной точности для той же ширины бит.
См., например, вывод этого небольшого фрагмента:
int main() {
int x = 43046721;
float y = x;
printf("%d\n", x);
printf("%f\n", y);
}
43046721
не может быть правильно отображен в 24-битной точности, доступной в 32-разрядном float
числе, поэтому вывод - это что-то в этих строках:
43046721
43046720.000000
Фактически, я ожидал бы, что любое нечетное число выше 16 777 216 будет иметь такую же проблему при преобразовании в 32-разрядный номер float
.
Несколько интересных моментов:
-
Это больше связано с неявным преобразованием int-to-float, чем с самим умножением.
-
Это не какое-либо среднее значение для C - например, Java также подвержена той же самой проблеме.
-
В большинстве компиляторов есть параметры оптимизации, которые могут повлиять на обработку таких преобразований, игнорируя определенные ограничения стандарта. В таком случае
(int)((float)x * 1.0f) == x
всегда может бытьtrue
, если компилятор оптимизирует преобразование вfloat
и обратно.
Ответ 3
Нет, поведение является реализацией, поскольку C и С++ не требуют IEEE-754, хотя это наиболее распространенное представление на сегодняшний день.
Чтобы убедиться, что используется IEEE-754:
- в C, используйте
#ifdef __STDC_IEC_559__
- в С++, используйте константы
std::numeric_limits<float>::is_iec559
Ответ 4
Нет, это абсолютно неверно для всех целых чисел из-за типа cast. проверьте код.
#include <stdio.h>
int main()
{
int i = 0;
for (; i < 2147483647; ++i) {
if ((int)(i * 1.0f) != i) {
printf("not equal\n");
break;
}
}
printf("out of the loop\n");
getchar();
return 0;
}
Этот код предполагает, что вы берете 32-битное целое число