为什么Java的Math.round()无法处理这个数字?

时间:2016-05-17 03:14:02

标签: java rounding

我有这样的代码:

System.out.println("Math.round(1423562400L) => " + Math.round(1423562400L));

结果如下:

Math.round(1423562400L) => 1423562368

这个值是一个64位整数,但它很容易适合32位整数,它应该是一个双精度数。发生了什么事?

3 个答案:

答案 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()接受doublefloat,所以当您通过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 的原因

enter image description here

图片来源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