我有这段代码
public class LimitTest{
public static void main(String[] args){
long l;
double d;
l = 9223372036854775807L;// The largest number a long can hold.
d = l;
System.out.println(l);
System.out.println(d);
System.out.println(l == d);
}
}
现在,它产生的结果有点出乎意料,但同样,我对类型转换不是很有经验。
输出
9223372036854775807
9.223372036854776E18
true
现在,打印的两个数字显然是 NOT EQUAL ,那么为什么l == d
会返回true
?
答案 0 :(得分:5)
变量l
和d
具有不同的类型,因此表达式long == double
会将long
转换为double
...
P.S。 l
是一个糟糕的变量名称imho,因为它在浏览代码时看起来很像1
。
答案 1 :(得分:2)
l == d
会返回true
,因为l
会自动提升为double
,然后会将结果(与d
相同)进行比较d
。
如果您有兴趣,可以阅读JLS中的促销规则:
答案 2 :(得分:2)
那么为什么l == d会返回true;
因为long
在比较之前转换为double
。因此结果是真的。
这在JLS - Section 5.6.2中指定:
应用扩展基元转换(第5.1.2节)来转换以下规则指定的一个或两个操作数:
- 如果任一操作数的类型为double,则另一个操作数将转换为double。
您看到double
的结果不同,因为并非所有long
值都可以由唯一的double
值表示。因此,对于单个long值,您可能有许多double值。从long
转换为double
时可能会失去精确度。
将int或long值扩展为float,或将long值的转换为double ,可能会导致精度损失 - 也就是说,结果可能会失去一些最不重要的价值的一部分。
答案 3 :(得分:2)
为了比较两个值,它们必须具有相同的类型。这里long值被隐式转换为double类型,转换结果给出了与赋值相同的值。
这些值首先是不同的,因为double类型具有较少的“重要性”(它具有用于存储实际数字的53位尾数;其余位用于符号和指数)而不是长(所有64位)。并非所有长值都可以表示为唯一的双精度值。
答案 4 :(得分:2)
9223372036854775807
和9.223372036854776E18
等于
请注意,精度922337203685477
的前15位数字是相同的。第一个数字5807
的其余部分将四舍五入为6,以便可以附加E18
。
9223372036854775807
是:
9.223372036854775807 x 10^18 == 9.223372036854775807E18
比较:
9.223372036854775807E18
9.223372036854776E18
该值的存储精度高于显示的值,请参阅此说明以获取证据:
long l;
double d;
l = Long.MAX_VALUE;// The largest number a long can hold.
d = l; //This is implicitly cast to (double)
System.out.println("long: " + l);
System.out.println("double: " + d);
System.out.println("double back to long: " + (long) d);
长:9223372036854775807
双倍:9.223372036854776E18
双回长:9223372036854775807
还有存储浮点数和双打数的次要问题。虽然整数类型(byte,short,int,long)是精确的,但float和double使用IEEE754尾数指数样式,它允许它们表示更大范围的数字但精度更低。 http://en.wikipedia.org/wiki/IEEE_754-1985