我很好奇为什么浮动文字必须如此声明:
float f = 0.1f;
Run Code Online (Sandbox Code Playgroud)
代替
float f = 0.1;
Run Code Online (Sandbox Code Playgroud)
为什么默认类型是double,为什么编译器不能通过查看赋值的左侧来推断它是一个浮点数?谷歌只会出现关于默认值的解释,而不是为什么会这样.
Ste*_*n C 36
为什么默认类型为double?
对于Java语言的设计者来说,这是一个最好的问题.他们是唯一知道为什么做出语言设计决定的真正原因的人.但我希望推理有以下几点:
他们需要区分两种类型的文字,因为它们实际上意味着从数学角度来看不同的价值观.
假设他们将"浮动"作为文字的默认值,请考虑此示例
// (Hypothetical "java" code ... )
double d = 0.1;
double d2 = 0.1d;
Run Code Online (Sandbox Code Playgroud)
在上面,d和d2实际上会有不同的值.在第一种情况下,低float精度double值在赋值点被转换为更高的精度值.但你无法恢复那里没有的精度.
我假设一种语言设计,其中这两个陈述都是合法的,并且意味着不同的东西是一个不好的想法......考虑到第一个陈述的实际含义与"自然"含义不同.
按照他们的方式做到这一点:
double d = 0.1f;
double d2 = 0.1;
Run Code Online (Sandbox Code Playgroud)
既合法又意味着不同的东西.但是在第一个声明中,程序员的意图是明确的,第二个声明是"自然"的意思是程序员得到的.在这种情况下:
float f = 0.1f;
float f2 = 0.1; // compilation error!
Run Code Online (Sandbox Code Playgroud)
......编译器选择不匹配.
我猜测使用浮点数是例外而不是规则(使用双打而不是)与现代硬件,所以在某些时候,假设用户在写作时想要0.1f是有意义的
float f = 0.1;
他们已经可以做到了.但问题是提出了一组有效的类型转换规则......而且很简单,你不需要Java -ology的学位来实际理解.0.1在不同的背景下有不同的意思会让人感到困惑.考虑一下:
void method(float f) { ... }
void method(double d) { ... }
// Which overload is called in the following?
this.method(1.0);
Run Code Online (Sandbox Code Playgroud)
编程语言设计很棘手.一个领域的变化会对其他领域产生影响.
更新以解决@supercat引发的一些问题.
@supercat:鉴于上述重载,将为方法(16777217)调用哪个方法?那是最好的选择吗?
我错误地评论了...编译错误.实际上答案是method(float).
JLS说:
如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符.Java编程语言使用选择最具体方法的规则.
...
[符号m1和m2表示适用的方法.]
[if] m2不是通用的,m1和m2适用于严格或 松散的调用,并且m1具有形式参数类型S1,...,Sn和m2具有形式参数类型T1,...,Tn,类型对于所有i(1≤i≤n,n = k),Si对于参数ei比Ti更具特异性.
...
上述条件是一种方法可能比另一种方法更具体的唯一情况.
如果S <:T(§4.10),则类型S对于任何表达式比类型T更具体.
在这种情况下,我们正在比较method(float),method(double)哪些都适用于呼叫.从float<:,double它更具体,因此method(float)将被选中.
@supercat:这样的行为可能会导致问题,例如表达式喜欢
int2 = (int) Math.Round(int1 * 3.5)或被long2 = Math.Round(long1 * 3.5)替换为int1 = (int) Math.Round(int2 * 3)或long2 = Math.Round(long1 * 3)这种变化看起来无害的,但前两个表达式是正确的达到
613566756或2573485501354568后两个失败以上5592405[最后是完全虚假的上方715827882.
如果你在谈论一个人做出这种改变......好吧.
但是,编译器不会在您的背后进行更改.例如,int1 * 3.5有类型double(int转换为a double),所以你最终调用了Math.Round(double).
作为一般规则,Java算法将隐式地从"较小"数字类型转换为"较大"数字类型,但不会从"较大"转换为"较小".
但是,您仍然需要小心,因为(在您的舍入示例中):
整数和浮点的乘积可能无法用足够的精度表示,因为(例如)a float的精度比精度要低int.
将结果Math.round(double)转换为整数类型可以导致转换为整数类型的最小/最大值.
但所有这些都说明编程语言中的算术支持是棘手的,并且对于新的或不谨慎的程序员来说,存在不可避免的问题.