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

Int to float conversion выдает предупреждение?

Удивительно, что даже когда значение может быть преобразовано, преобразование int в float всегда дает предупреждение. Почему это?

int i = 0;
float f = 0; // warning here

// I thought this was an implicit conversion,
// meaning it is convertible with no warnings.
f = i;      // another warning here

Предупреждение:

warning C4244: '=' : conversion from 'int' to 'float', possible loss of data
4b9b3361

Ответ 1

Это зависит от того, сколько бит у вас есть в типе int. Поплавок, который является одиночной точностью IEEE754, представляет собой 32-битное значение, но некоторые из этих битов назначаются экспоненте, а это означает, что не все доступны для точности.

Если ваш тип int имеет более высокую точность, чем ваш float, вы можете потерять точность на высоком конце.

Другими словами, он не может различать INT_MAX и INT_MAX - 1.

Решение в этом случае - использовать более широкий тип с плавающей точкой (double), хотя технически вы можете найти реализацию с 256-битным типом int, в этом случае вам придется найти другой способ: -)

Этот ответ содержит краткий обзор того, как работают форматы с плавающей запятой, в том числе тот факт, что только 23 из 32 бит доступны для точности мантиссы.

Ответ 2

Я ответил на аналогичный вопрос:

Почему GCC предупреждает об этом неявном преобразовании?

Причина в том, что int необходимо округлить, когда он был добавлен в float, потому что float не может содержать всю точность int в этом случае.

В вашем случае float имеет только около 24 бит точности. В то время как int имеет 32 бита точности, следовательно, некоторая точность - это потеря этого броска, поэтому предупреждение.

Ответ 3

Просто для удовольствия, попробуйте это и посмотрите, какой результат (подсказка, вы бы ожидали, что все цифры будут одинаковыми, не так ли?):

int i1(INT_MAX), i2;

float f(i1);

i2 = f;

std::cout << i1 << ' ' << f << ' ' << i2 << '\n';

Ну, ответы, которые я получаю, следующие:

2147483647 2.14748e+009 -2147483648

Итак, компилятор совершенно прав, чтобы указать, что что-то может пойти не так, как с актерским составом, но это недостаточно умно, чтобы точно знать, потому что оно будет иметь тенденцию происходить только на концах численного диапазона. Это всегда лучше для static_cast < > на мой взгляд, для большей ясности, и показать компилятору, что это то, что вы намеревались.

Кстати, я не совсем уверен, почему происходит этот результат. Возможно, кто-то еще может объяснить!

Ответ 4

//Я думал, что это неявное преобразование означает, что оно скрыто с помощью никаких предупреждений?

Нет, это не то, что это значит. Это просто означает, что вы можете присвоить значение одного типа объекту другого типа без явного преобразования (т.е. Приведения), и значение будет преобразовано неявно.

И в этом случае предупреждение может быть уместным. Если int и float являются 32 битами (что типично, но не универсально), то все значения типа int находятся в диапазоне float, но существует множество значений типа int, которые не могут будет отображаться точно в типе float.

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