我觉得这个问题很直接。但这里有一个例子。
下面的例子是OK的。我可以取四舍五入,这里没有截断。
public static void main(String[] args) {
double d = 9.9;
long l = (long)d;
System.out.println(l);
}
输出:9
现在number超出了long的范围:
public static void main(String[] args) {
double d = 99999999999999999999999999999999.9;
long l = (long)d;
System.out.println(l);
}
输出:9223372036854775807
这个问题困扰着我。我不能用完全不同的数字继续工作。我宁愿得到一个错误或异常。
在Java中有什么方法可以检测到这个吗?
可以与Long.MIN_VALUE
和Long.MAX_VALUE
进行比较:
public static boolean fitsLong(double d) {
return d >= Long.MIN_VALUE && d < Long.MAX_VALUE;
}
更复杂的方法是使用BigDecimal
:
double value = 1234567.9;
long l = BigDecimal.valueOf(value)
.setScale(0, RoundingMode.HALF_EVEN)
.longValueExact(); // 1234568
double value = 99999999999999999999999999999999.9;
long l = BigDecimal.valueOf(value)
.setScale(0, RoundingMode.HALF_EVEN)
.longValueExact(); // ArithmeticException
这样可以控制舍入的执行方式。
你可能会问,为什么fitsLong
: d < Long.MAX_VALUE
有严格的不等式。实际上,这是因为Long.MAX_VALUE
本身不能表示为双精度数。当您强制转换(double)Long.MAX_VALUE
时,double
类型中没有足够的精度来表示它,因此选择最接近的可表示值9223372036854775808.0
(Long_MAX_VALUE+1.0
)。因此,如果它是d <= Long.MAX_VALUE
,它将返回true
作为数字,实际上稍微大一点,因为在这个比较中Long.MAX_VALUE
常量被提升为双精度类型。另一方面,Long.MIN_VALUE
可以精确地表示为double
类型,因此这里我们有>=
。
同样有趣的是为什么下面的工作:
double value = -9223372036854775809.9; // Long.MIN_VALUE-1.9
System.out.println(fitsLong(value)); // returns true
那是因为你实际上没有从Long.MIN_VALUE
中减去任何东西。看到:
double d1 = Long.MIN_VALUE;
double d2 = -9223372036854775809.9;
System.out.println(d1 == d2); // true
双精度不足以区分-9223372036854775808
和-9223372036854775809.9
,因此它们实际上是相同的双精度数。在编译过程中,它被转换成二进制形式,这两个数字的二进制形式是相同的。因此,编译后的程序无法区分-9223372036854775808
或-9223372036854775809.9
是否在源代码中。
如果你觉得这仍然是问题,从String
:
BigDecimal
:long l = new BigDecimal("-9223372036854775808.2")
.setScale(0, RoundingMode.HALF_EVEN)
.longValueExact(); // ok, -9223372036854775808
long l = new BigDecimal("-9223372036854775808.9")
.setScale(0, RoundingMode.HALF_EVEN)
.longValueExact(); // ArithmeticException
当您将浮点类型强制转换为int
或long
时,结果要么是最接近的整数(向零舍入),要么是int
或long
的MIN_VALUE
或MAX_VALUE
。参考JLS 5.1.3
因此,一种替代方法是进行类型转换,然后测试适当的MIN_VALUE
或MAX_VALUE
。
注意Long.MAX_VALUE
是9223372036854775807
…这是您的测试程序输出的数字!
(但是,如果您将浮点类型强制转换为byte
, char
或short
,则此操作不起作用。