为什么 Java 的 Math.round() 不能处理这个数字?
Why Java's Math.round() cannot handle this number?
我有这样的代码:
System.out.println("Math.round(1423562400L) => " + Math.round(1423562400L));
结果是这样的:
Math.round(1423562400L) => 1423562368
此值是一个 64 位整数,但它很容易适合 32 位整数,而 32 位整数应该适合双精度数。这是怎么回事?
我认为 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
根据 JLS,
15.12.2.5. Choosing the Most Specific Method
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error.
由此可见Math.round(float)
is more specific than Math.round(double)
, and since they're both valid overloads,编译器选择了前者,导致数据丢失
要更正您的输出,只需将 1423562400L
更改为 1423562400d
。
注意Math.round的签名是
public static int round(float a)
它接受一个 32 位的浮点数,现在你把一个 64 位的长到这个方法,
它将 long 切割为 int,然后将其转换为 float。
System.out.println(Math.round((int)1423562400L));
System.out.println(Math.round((float)1423562400L));
代码也打印 1423562368
如果你明确地把它转换成double
那么结果是正确的
1423562400
我有这样的代码:
System.out.println("Math.round(1423562400L) => " + Math.round(1423562400L));
结果是这样的:
Math.round(1423562400L) => 1423562368
此值是一个 64 位整数,但它很容易适合 32 位整数,而 32 位整数应该适合双精度数。这是怎么回事?
我认为 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
根据 JLS,
15.12.2.5. Choosing the Most Specific Method
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error.
由此可见Math.round(float)
is more specific than Math.round(double)
, and since they're both valid overloads,编译器选择了前者,导致数据丢失
要更正您的输出,只需将 1423562400L
更改为 1423562400d
。
注意Math.round的签名是
public static int round(float a)
它接受一个 32 位的浮点数,现在你把一个 64 位的长到这个方法, 它将 long 切割为 int,然后将其转换为 float。
System.out.println(Math.round((int)1423562400L));
System.out.println(Math.round((float)1423562400L));
代码也打印 1423562368
如果你明确地把它转换成double 那么结果是正确的
1423562400