例:
float timeRemaining = 0.58f;
为什么f
在此数字末尾需要?
例:
float timeRemaining = 0.58f;
为什么f
在此数字末尾需要?
double & int
。
Answers:
您的浮动声明包含两个部分:
timeRemaining
的类型为float
。0.58
给此变量。该问题出现在第2部分中。
右侧将自行评估。根据C#规范,包含不带后缀的小数点的数字将解释为double
。
因此,我们现在有了一个double
要分配给type变量的值float
。为此,必须存在从double
到的隐式转换float
。没有这种转换,因为您可能(在这种情况下确实)会在转换中丢失信息。
原因是编译器使用的值并不是真正的0.58,而是最接近0.58的浮点值,即对于0.57999999999999978655962351581366 ...double
和对于0.57999994605757796478271484375float
。
严格来说,f
不需要。您可以f
通过将值强制转换为来避免使用后缀float
:
float timeRemaining = (float)0.58;
(float) 0.58
工作?您之前说过,没有转换,因为可能会丢失信息,那么转换将如何起作用?
2.4
在其他任何地方都被解释为双精度型。2.不允许隐式变窄转换(如从double到float)。如果您想对这些规则作例外处理,那么您必须有充分的理由。节省1个击键可能不够好。
因为有几个数字类型,编译器可以用它来表示该值0.58
:float
,double
和decimal
。除非您同意编译器为您选择一个,否则您必须消除歧义。
的文档double
指出,如果您自己未指定类型,则编译器将始终选择double
任何实数值文字的类型:
默认情况下,赋值运算符右侧的实数值文字被视为double。但是,如果要将整数视为双精度数,请使用后缀d或D。
附加后缀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
,需要明确指定在涉及混合操作数的所有情况下应发生的情况,或者允许在一种类型之间执行隐式转换。仅方向 微软选择跟随Java的发展方向,以允许偶尔偏向于精度的方向,但是却经常牺牲正确性并通常造成麻烦。
在几乎所有情况下,取double
最接近特定数字量float
的float
值并将其分配给a将产生最接近该相同量的值。有一些特殊情况,例如值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 ^ 308float
的最佳double
表示形式与通过转换该数量的最佳表示形式获得的表示形式相匹配。同样,最佳float
表示形式10 ^ 309与float
通过转换该double
数量的最佳表示形式获得的表示形式相匹配。
不幸的是,在不需要显式转换的方向上进行转换的准确性很少。将float
值的最佳表示形式转换为double
几乎不会产生double
与该值的最佳表示形式特别接近的任何信息,并且在某些情况下,结果可能相差数百个数量级(例如,将float
10 ^ 40的最佳表示形式转换为double
将产生一个比最佳double
表示形式10 ^ 300大的值。
,,转换规则就是它们的本质,因此,在“安全”方向上转换值时,必须忍受愚蠢的类型转换和后缀,并且要注意在危险方向上隐式的类型转换,这经常会产生假结果。
double
。