为什么声明浮动时需要“f”?

例:

float timeRemaining = 0.58f; 

为什么在数字的最后需要f

您的浮动声明包含两部分:

  1. 它声明variablestimeRemaining的types是float
  2. 它为这个variables赋值0.58

问题出现在第2部分。

右边是自己评估的。 根据C#规范,包含一个没有后缀的小数点的数字被解释为double

所以我们现在有一个double值,我们要分配给一个floattypes的variables。 为了做到这一点,必须有一个从doublefloat的隐式转换。 没有这样的转换,因为你可能(在这种情况下)在转换中丢失信息。

原因是编译器使用的值并不是真的0.58,而是最接近0.58的浮点值,即0.57999999999999978655962351581366 …为double ,精确地为0.579999946057796478271484375。

严格来说, f不是必需的。 您可以通过将值转换为float来避免使用f后缀:

 float timeRemaining = (float)0.58; 

因为编译器可以使用几种数字types来表示值0.58floatdoubledecimal 。 除非编译器为你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.58float timeRemaining的转换可能会丢失信息,所以编译器拒绝隐式应用它。 如果添加明确的转换,则执行转换; 如果你添加f后缀,那么不需要转换。 在这两种情况下,代码将被编译。

问题在于.NET为了允许执行某些types的隐式操作(包括floatdouble ,需要明确指定在涉及混合操作数的所有情况下应该发生的情况,还是允许在要执行的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转换,这样往往会产生虚假的结果。