为什么声明浮动时需要“f”?
例:
float timeRemaining = 0.58f;
为什么在数字的最后需要f
?
您的浮动声明包含两部分:
- 它声明variables
timeRemaining
的types是float
。 - 它为这个variables赋值
0.58
。
问题出现在第2部分。
右边是自己评估的。 根据C#规范,包含一个没有后缀的小数点的数字被解释为double
。
所以我们现在有一个double
值,我们要分配给一个float
types的variables。 为了做到这一点,必须有一个从double
到float
的隐式转换。 没有这样的转换,因为你可能(在这种情况下)在转换中丢失信息。
原因是编译器使用的值并不是真的0.58,而是最接近0.58的浮点值,即0.57999999999999978655962351581366 …为double
,精确地为0.579999946057796478271484375。
严格来说, f
不是必需的。 您可以通过将值转换为float
来避免使用f
后缀:
float timeRemaining = (float)0.58;
因为编译器可以使用几种数字types来表示值0.58
: float
, double
和decimal
。 除非编译器为你select一个,否则你必须消除歧义。
double
状态的文档指出,如果你自己没有指定types,编译器总是selectdouble
作为任何实数字面值的types:
默认情况下,赋值运算符右侧的实数字面值被视为double。 但是,如果要将整数视为double,请使用后缀d或D.
附加后缀f
创build一个float
; 后缀d
创build一个double
; 后缀m
创build一个decimal
。 所有这些也以大写forms工作。
然而,这还不足以解释为什么这不能编译:
float timeRemaining = 0.58;
答案中缺less的一半是,从double
0.58
到float
timeRemaining
的转换可能会丢失信息,所以编译器拒绝隐式应用它。 如果添加明确的转换,则执行转换; 如果你添加f
后缀,那么不需要转换。 在这两种情况下,代码将被编译。
问题在于.NET为了允许执行某些types的隐式操作(包括float
和double
,需要明确指定在涉及混合操作数的所有情况下应该发生的情况,还是允许在要执行的types之间进行隐式转换仅在一个方向上; 微软select跟随Java的领导,允许偶尔有利于精确的方向,但往往牺牲正确性,一般会造成麻烦。
在几乎所有情况下,将最接近特定数字量的double
值分配给一个float
将产生最接近该相同数量的float
值。 有几个angular落案例,如价值9,007,199,791,611,905; 最好的float
利差为9,007,200,328,482,816(折合536,870,911),但是最好的float
利率为9,007,199,254,740,992(亏损536,870,913)。 但是,一般来说,将某个数量的最佳double
表示转换为float
可能会产生最好的float
表示,或者两个本质上同样好的表示之一。
请注意,这种理想的行为即使在极端情况下也适用。 例如,数量10 ^ 308的最佳float
表示与通过转换该数量的最佳double
表示达到的float
表示相匹配。 同样,10 ^ 309的最佳float
表示与通过转换该数量的最佳double
表示forms实现的float
表示匹配。
不幸的是,不需要明确演员指导的转换很less接近准确。 将一个值的最佳float
表示转换为double
值很less会产生特别接近该值的最佳double
表示的任何值,在某些情况下,结果可能会被closures数百个数量级(例如,将最佳float
表示法转换为10 ^ 40 double
会产生一个比10 ^ 300的最佳double
表示更大的值。
唉,转换规则就是这样,所以在“安全”方向转换价值的时候,要用傻傻的types和后缀来生活,要小心隐藏的types转换,这样往往会产生虚假的结果。