92

例子:

float timeRemaining = 0.58f;

为什么f在这个数字的末尾是必需的?

4

3 回答 3

101

Your declaration of a float contains two parts:

  1. It declares that the variable timeRemaining is of type float.
  2. It assigns the value 0.58 to this variable.

The problem occurs in part 2.

The right-hand side is evaluated on its own. According to the C# specification, a number containing a decimal point that doesn't have a suffix is interpreted as a double.

So we now have a double value that we want to assign to a variable of type float. In order to do this, there must be an implicit conversion from double to float. There is no such conversion, because you may (and in this case do) lose information in the conversion.

The reason is that the value used by the compiler isn't really 0.58, but the floating-point value closest to 0.58, which is 0.57999999999999978655962351581366... for double and exactly 0.579999946057796478271484375 for float.

Strictly speaking, the f is not required. You can avoid having to use the f suffix by casting the value to a float:

float timeRemaining = (float)0.58;
于 2012-07-21T07:29:50.457 回答
38

因为编译器可以使用几种数字类型来表示值0.58:float和. 除非您对编译器为您选择一个没问题,否则您必须消除歧义。doubledecimal

的文档double指出,如果您自己不指定类型,编译器总是选择double任何实数值文字的类型:

默认情况下,赋值运算符右侧的实数文字被视为双精度值。但是,如果您希望将整数视为双精度数,请使用后缀 d 或 D。

附加后缀f会创建一个float; 后缀d创建一个double; 后缀m创建一个decimal. 所有这些也都以大写形式工作。

但是,这仍然不足以解释为什么它不能编译:

float timeRemaining = 0.58;

答案中缺少的一半是从double 0.58到的转换float timeRemaining可能会丢失信息,因此编译器拒绝隐式应用它。如果添加显式转换,则会执行转换;如果添加f后缀,则无需转换。在这两种情况下,代码都会编译。

于 2012-07-17T09:35:37.147 回答
3

问题是.NET,为了允许执行某些类型的隐式操作,涉及floatdouble,需要明确指定在涉及混合操作数的所有场景中应该发生什么,或者允许在一个类型之间执行隐式转换只有方向;微软选择跟随 Java 的领导,允许偶尔偏爱精确但经常牺牲正确性并且通常会产生麻烦的方向。

在几乎所有情况下,取double最接近特定数字量的值并将其分配给 afloat将产生float最接近该相同量的值。有一些极端情况,例如值 9,007,199,791,611,905;最佳float表示将是 9,007,200,328,482,816(相差 536,870,911),但将最佳double表示(即 9,007,199,791,611,904)转换为float9,007,199,254,740,992(相差 536,870,913)。但是,一般而言,将double某个数量的最佳表示转换为float将产生可能的最佳float表示,或者是本质上同样好的两种表示之一。

请注意,这种理想的行为即使在极端情况下也适用;例如,float数量 10^308的最佳表示与float通过转换该double数量的最佳表示所获得的表示相匹配。同样,float10^309 的最佳表示与float通过转换该double数量的最佳表示所获得的表示相匹配。

不幸的是,在不需要显式转换的方向上的转换很少能接近准确。float将一个值的最佳表示转换为double很少会产生特别接近double该值的最佳表示的任何东西,并且在某些情况下,结果可能会相差数百个数量级(例如,将float10^40 的最佳表示转换为double将产生比较大于double10^300 的最佳表示的值。

唉,转换规则就是这样,所以在“安全”方向转换值时,必须忍受使用愚蠢的类型转换和后缀,并小心在危险方向上的隐式类型转换,这会经常产生虚假结果。

于 2013-06-21T23:37:02.450 回答