Пример:
float timeRemaining = 0.58f;
Почему f
в конце этого числа обязательно стоит?
c#
floating-point
Томас
источник
источник
double
.double & int
.Ответы:
Ваше объявление float состоит из двух частей:
timeRemaining
имеет типfloat
.0.58
этой переменной.Проблема возникает в части 2.
Правая часть оценивается сама по себе. Согласно спецификации C # число, содержащее десятичную точку без суффикса, интерпретируется как
double
.Итак, теперь у нас есть
double
значение, которое мы хотим присвоить переменной типаfloat
. Для этого должно быть неявное преобразование изdouble
вfloat
. Такого преобразования нет, потому что вы можете (и в этом случае потеряете) информацию при преобразовании.Причина в том, что значение, используемое компилятором, на самом деле не 0,58, а значение с плавающей запятой, наиболее близкое к 0,58, которое составляет 0,57999999999999978655962351581366 ... для
double
и точно 0,579999946057796478271484375 дляfloat
.Строго говоря,
f
это не обязательно. Вы можете избежать использованияf
суффикса, приведя значение кfloat
:float timeRemaining = (float)0.58;
источник
(float) 0.58
работать? Вы сказали ранее, что преобразования нет, потому что информация может быть потеряна, тогда почему приведение будет работать?2.4
везде интерпретируется как двойное. 2. Неявные сужающие преобразования (например, из double в float) не допускаются. Если вы хотите сделать исключение из этих правил, то у вас должна быть очень веская причина. Сохранение одного нажатия клавиши вряд ли будет достаточно.Поскольку существует несколько числовых типов , которые компилятор может использовать для представления значения
0.58
:float
,double
иdecimal
. Если вы не согласны с тем, что компилятор выберет один за вас, вы должны устранить неоднозначность.В документации для
double
указано, что если вы сами не укажете тип, компилятор всегда выберетdouble
тип любого действительного числового литерала:Добавление суффикса
f
создаетfloat
; суффиксd
создаетdouble
; суффиксm
создаетdecimal
. Все они также работают в верхнем регистре.Однако этого все еще недостаточно, чтобы объяснить, почему это не компилируется:
float timeRemaining = 0.58;
Недостающая половина ответа заключается в том, что преобразование из
double
0.58
кfloat
timeRemaining
потенциально теряет информацию, так что компилятор отказывается применять его в неявном виде . Если вы добавляете явное приведение, преобразование выполняется; если вы добавитеf
суффикс, преобразование не потребуется. В обоих случаях код будет компилироваться.источник
int
и одно дляdouble
.double a = 0.69f;
?float
вdouble
.Проблема в том, что .NET, чтобы разрешить выполнение некоторых типов неявных операций с участием
float
иdouble
, необходимо либо явно указать, что должно происходить во всех сценариях, включающих смешанные операнды, либо разрешить неявные преобразования между типами, которые будут выполняться в одном только направление; Microsoft решила последовать примеру Java, выбрав направление, которое иногда способствует точности, но часто жертвует правильностью и в целом создает проблемы.Практически во всех случаях
double
значение, наиболее близкое к определенной числовой величине, и присвоить его a,float
будет полученоfloat
значение, наиболее близкое к той же величине. Есть несколько угловых случаев, например, значение 9,007,199,791,611,905; наилучшимfloat
представлением будет 9 007 200 328 482 816 (что меньше на 536 870 911), но приведение лучшегоdouble
представления (т.е. 9 007 199 791 611 904)float
даст 9 007 199 254 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.Увы, правила преобразования таковы, каковы они есть, поэтому при преобразовании значений в «безопасном» направлении приходится смириться с использованием глупых приведений типов и суффиксов и быть осторожными с неявными приведениями типов в опасном направлении, которые часто приводят к ложным результатам.
источник