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

Почему "f" требуется при объявлении float?

Пример:

float timeRemaining = 0.58f;

Почему в конце номера требуется f?

4b9b3361

Ответ 1

Ваше объявление о поплавке содержит две части:

  • Он объявляет, что переменная timeRemaining имеет тип float.
  • Он присваивает значение 0.58 этой переменной.

Проблема возникает в части 2.

Правая часть оценивается сама по себе. Согласно спецификации С#, число, содержащее десятичную точку, которая не имеет суффикса, интерпретируется как double.

Итак, теперь мы имеем значение double, которое мы хотим присвоить переменной типа float. Для этого должно быть неявное преобразование от double до float. Такое преобразование отсутствует, потому что вы можете (и в этом случае делать) потерять информацию при преобразовании.

Причина в том, что значение, используемое компилятором, на самом деле не 0,58, но значение с плавающей запятой, ближайшее к 0,58, которое составляет 0,57999999999999978655962351581366... для double и ровно 0,579999946057796478271484375 для float.

Строго говоря, f не требуется. Вы можете избежать использования суффикса f, задав значение :

float timeRemaining = (float)0.58;

Ответ 2

Поскольку существует несколько числовых типов, которые компилятор может использовать для представления значения 0.58: float, double и decimal. Если вы не согласны с тем, что компилятор выбирает один для вас, вам необходимо устранить проблему.

В документации для double указано, что если вы не укажете тип самостоятельно, компилятор всегда выбирает double как тип любого действительного числового литерала:

По умолчанию действительный числовой литерал в правой части задания оператор рассматривается как двойной. Однако, если вы хотите, чтобы целое число для того, чтобы считаться двойным, используйте суффикс d или D.

Добавление суффикса f создает float; суффикс d создает double; суффикс m создает decimal. Все они также работают в верхнем регистре.

Однако этого все еще недостаточно, чтобы объяснить, почему это не скомпилируется:

float timeRemaining = 0.58;

Недопустимая половина ответа заключается в том, что преобразование из double 0.58 в float timeRemaining потенциально теряет информацию, поэтому компилятор отказывается применять его неявно. Если вы добавляете явное преобразование, выполняется преобразование; если вы добавите суффикс f, то преобразование не потребуется. В обоих случаях код будет компилироваться.

Ответ 3

Проблема заключается в том, что .NET, чтобы позволить выполнять некоторые типы неявных операций с использованием float и double, необходимо либо явно указать, что должно происходить во всех сценариях, связанных с смешанными операндами, либо разрешать неявные конверсии между типами, которые должны выполняться только в одном направлении; Microsoft предпочла следовать примеру Java, позволяя направление, которое иногда способствует точности, но часто приносит в жертву правильность и обычно создает проблемы.

Почти во всех случаях значение double, которое ближе всего к определенной числовой величине и присваивает его float, даст значение float, которое ближе всего к той же самой величине. Существует несколько угловых случаев, таких как значение 9 007 199 691 611 905; наилучшее представление float было бы 9 007 200 328 482 816 (которое отключено на 536 870 911), но отличное представление double (т.е. 9 007 199 671 611 904) до float дает 9 007 199 994 740 992 (что не соответствует 536 870 913). В общем случае преобразование наилучшего представления double некоторой величины в float либо даст наилучшее представление float, либо одно из двух представлений, которые по существу одинаково хороши.

Обратите внимание, что это желаемое поведение распространяется даже на крайности; например, лучшее представление float для величины 10 ^ 308 соответствует представлению float, полученному путем преобразования наилучшего представления double этой величины. Точно так же наилучшее представление float 10 ^ 309 соответствует представлению float, достигаемому путем преобразования наилучшего представления double этой величины.

К сожалению, конверсии в направлении, не требующем явного приведения, редко где-то близки к точности. Преобразование наилучшего представления float значения в double редко приведет к чему-либо, особенно близкому к лучшему представлению double этого значения, и в некоторых случаях результат может быть отключен на сотни порядков (например, преобразование Лучшее float представление от 10 ^ 40 до double даст значение, которое сравнивается больше, чем лучшее double представление 10 ^ 300.

Увы, правила конверсии - это то, что они есть, поэтому нужно жить с использованием глупых приемов и суффиксов при преобразовании значений в "безопасном" направлении и быть осторожным с неявными приведениями в опасном направлении, которые часто дают фиктивные результаты.