are*_*naq 7 java double casting truncate long-integer
我认为这个问题很简单.但这是一个例子.
以下示例正常.我可以进行四舍五入,这里没有截断.
public static void main(String[] args) {
double d = 9.9;
long l = (long)d;
System.out.println(l);
}
Run Code Online (Sandbox Code Playgroud)
输出:
9
Run Code Online (Sandbox Code Playgroud)
现在数字超出了长期范围:
public static void main(String[] args) {
double d = 99999999999999999999999999999999.9;
long l = (long)d;
System.out.println(l);
}
Run Code Online (Sandbox Code Playgroud)
输出:
9223372036854775807
Run Code Online (Sandbox Code Playgroud)
这个让我烦恼.我不能继续使用完全不同的数字.我宁愿得到错误或异常.
有没有办法在Java中检测到这个?
Tag*_*eev 12
你可以将它与Long.MIN_VALUE和Long.MAX_VALUE:
public static boolean fitsLong(double d) {
return d >= Long.MIN_VALUE && d < Long.MAX_VALUE;
}
Run Code Online (Sandbox Code Playgroud)
更软化的方法是使用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
Run Code Online (Sandbox Code Playgroud)
这样您就可以控制舍入的执行方式.
你可能会问,为什么在以下方面存在严重的不平等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常量被提升为double类型.另一方面Long.MIN_VALUE可以在double类型中准确表示,因此我们在这里>=.
另外有趣的是为什么以下工作原理:
double value = -9223372036854775809.9; // Long.MIN_VALUE-1.9
System.out.println(fitsLong(value)); // returns true
Run Code Online (Sandbox Code Playgroud)
那是因为你实际上并没有从中减去任何东西Long.MIN_VALUE.看到:
double d1 = Long.MIN_VALUE;
double d2 = -9223372036854775809.9;
System.out.println(d1 == d2); // true
Run Code Online (Sandbox Code Playgroud)
双精度不足以区分-9223372036854775808和-9223372036854775809.9,因此它实际上是相同的双数.在编译期间,它被转换为二进制形式,这两个数字的二进制形式是相同的.因此,已经编译的程序不能区分是否-9223372036854775808或-9223372036854775809.9在源代码中.
如果您认为它仍然是问题,请构建BigDecimal以下内容String:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
304 次 |
| 最近记录: |