Подтвердить что ты не робот

Точность умножения на 1.0 и int для плавающего преобразования

Можно ли считать, что условие (int)(i * 1.0f) == i истинно для любого целого числа i?

4b9b3361

Ответ 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-битное целое число