我有这样的代码:
System.out.println("Math.round(1423562400L) => " + Math.round(1423562400L));
结果如下:
Math.round(1423562400L) => 1423562368
这个值是一个64位整数,但它很容易适合32位整数,它应该是一个双精度数。发生了什么事?
答案 0 :(得分:7)
根据JLS,
<强> 15.12.2.5。选择最具体的方法
如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符。 Java编程语言使用选择最具体方法的规则。
非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个没有编译时类型错误的调用,那么一个方法比另一个方法更具体。
因此Math.round(float)
比Math.round(double)
更具体,因为它们都是valid overloads,编译器选择前者,导致数据丢失。
要更正输出,只需将1423562400L
更改为1423562400d
。
答案 1 :(得分:0)
我不认为Math.round()
具有支持long
参数的实现。这是Math.round()
签名。
Math.round(double a);
Math.round(float a);
Math.round()
接受double
或float
,所以当您通过long
时,您正在执行类似(long
转换为隐式浮动)
float x = 1423562400L;
System.out.println(Math.round(x));
要解决这个问题,您可以先将long
值添加到double
,它就会像魅力一样。
double x = 1423562400L;
System.out.println(Math.round(x));
为了简化你可以做到
Math.round((double)1423562400L)
或
Math.round(1423562400d)
以下图片显示隐式转化的工作原理以及 long
转换为 float
的原因
图片来源here
答案 2 :(得分:-1)
请注意,Math.round的签名是
public static int round(float a)
它接受一个32位浮点数,现在你把这个方法放了64位长, 它将long切成一个int,然后把它变成一个浮点数。
System.out.println(Math.round((int)1423562400L));
System.out.println(Math.round((float)1423562400L));
代码也打印1423562368
如果你将它转换为explitly双倍 那么结果是正确的
1423562400