为什么在声明浮点数时需要“ f”?


86

例:

float timeRemaining = 0.58f;

为什么f在此数字末尾需要?


4
可能是因为,否则将被视为double
乌威·基姆

2
0.58(不带f后缀)是double类型的文字,并且不能将double值分配给浮点数,就像不能将int值分配给字符串一样。但是,您可以将浮点值分配给双精度数,因为这是在扩展(C#将为您隐式转换该值,因为不会丢失精度)。
Dave New'7


@AVD尽管这是重复的,但上面的问题标题并未在可能的重复列表中产生您的链接。因此,这至少可以在更多搜索条件方面增加价值。
亚当·霍兹沃思

1
@AdamHouldsworth-所有道路都去了 double & int
adatapost

Answers:


96

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

  1. 它声明变量timeRemaining的类型为float
  2. 它将值分配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;

4
两个问题,您是如何得出数字'0.57999994605757796478271484375'的,它将如何(float) 0.58工作?您之前说过,没有转换,因为可能会丢失信息,那么转换将如何起作用?
SexyBeast

8
1.我使用的Windows计算器最多使用34位数字。2.我说没有隐式转换。强制转换是显式转换,因此您要明确告诉编译器您要进行转换,并且允许这样做。
Jeffrey Sax 2014年

有趣的...希望您仍在监视此帖子。在我正在查看的网络广播中,我被介绍到后缀“ m”。如何使Windows计算器显示.58作为浮点值?我尝试了几个按钮,看起来它们迫使这种情况发生,但是没有……一直保持0.58。我必须尊重一个非常了解他的工具的人……
user1585204 '16

我了解整个F浮点数,但为什么呢?当您声明变量时,将其声明为浮点数,因此在编译时应知道该值为浮点数。当您声明双重相同的东西时。这没有意义,因为您的float myvalue = 2.4; 现在,在编译时,编译器应该已经知道float是变量的类型。我想念什么吗?谢谢!
Frank G.

@FrankG。原因有两个:1.该表达式2.4在其他任何地方都被解释为双精度型。2.不允许隐式变窄转换(如从double到float)。如果您想对这些规则作例外处理,那么您必须有充分的理由。节省1个击键可能不够好。
杰弗里·萨克斯

36

因为有几个数字类型,编译器可以用它来表示该值0.58floatdoubledecimal。除非您同意编译器为您选择一个,否则您必须消除歧义。

的文档double指出,如果您自己未指定类型,则编译器将始终选择double任何实数值文字的类型:

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

附加后缀f会创建一个float;后缀d创建一个double; 后缀m创建一个decimal。所有这些都可以大写。

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

float timeRemaining = 0.58;

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


但是如果变量是浮点数,怎么可能是双精度或十进制,我错过了一些东西?
托马斯(Thomas)

@BlazArt是的,声明编译器的语句甚至没有尝试检查分配目标。这样做的原因将埋在编译器团队做出的设计选择中。我想最好是在可能出现混乱的情况下明确表述,否则麻烦执行而不是仅仅拥有两个规则(一个用于int和一个用于)过于昂贵double
亚当·霍尔兹沃思

@BlazArt:充实答案,请再看一遍。
2012年

1
关于信息丢失,您能告诉我有关存储它们的IEEE 754格式的实际转换是如何进行的吗?Double具有更高的精度,这是否意味着从float到double的转换将始终有效,例如double a = 0.69f;
SexyBeast

@Cupidvogel:是的,规范保证(在第6.1.2节中)“其他隐式数字转换不会丢失任何信息”,其中包括转换floatdouble
2014年

2

问题在于,.NET为了允许进行涉及float和的某些类型的隐式操作double,需要明确指定在涉及混合操作数的所有情况下应发生的情况,或者允许在一种类型之间执行隐式转换。仅方向 微软选择跟随Java的发展方向,以允许偶尔偏向于精度的方向,但是却经常牺牲正确性并通常造成麻烦。

在几乎所有情况下,取double最接近特定数字量floatfloat值并将其分配给a将产生最接近该相同量的值。有一些特殊情况,例如值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 ^ 308float的最佳double表示形式与通过转换该数量的最佳表示形式获得的表示形式相匹配。同样,最佳float表示形式10 ^ 309与float通过转换该double数量的最佳表示形式获得的表示形式相匹配。

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

,,转换规则就是它们的本质,因此,在“安全”方向上转换值时,必须忍受愚蠢的类型转换和后缀,并且要注意在危险方向上隐式的类型转换,这经常会产生假结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.