谜题3:长整除
该谜题涉及两个long型数值进行整除,所以称为长整除。先看看典型代码:
public class LongDivision{
public static void main(String[] args){
final long MICROS_PER_DAY = 24*60*60*1000*1000;
final long MILLIS_PER_DAY = 24*60*60*1000;
System.out.println(MICROS_PER_DAY /MILLIS_PER_DAY );
}
}
上面这段代码的输出结果是什么呢?看似程序打印的必定是1000,但运行后打印的结果是5,这是什么原因呢?
问题在于常数MICROS_PER_DAY的计算溢出了。虽然计算的结果放入long中,空间还有多余,但是这个结果并不适合放入int中,而恰巧的是整个计算的过程都是以int数值来进行运算的,在运算结束后,其结果才被提升为long。而此时早在计算时就已经溢出了,所以最终long里面的数值是一个比预期数值小了200倍的数,而MILLIS_PER_DAY的计算是正确的,所以最后打印的值比预期的值小了200倍,是5。
那么为什么计算是以int运算来执行的呢?因为所有进行运算的因子都是int类型的,所以当所有数运算完之后最开始的值是int类型的(此时发生溢出),之后才提升为long类型,所以,根据这个情况,我们可以将int类型的运算转换成long类型的变量,将代码改成如下即可:
public class LongDivision{
public static void main(String[] args){
final long MICROS_PER_DAY = 24L*60*60*1000*1000;
final long MILLIS_PER_DAY = 24L*60*60*1000;
System.out.println(MICROS_PER_DAY /MILLIS_PER_DAY );
}
}
这个示例告诉我们,当你在操作很大的数字时,千万要提防溢出。即使用来保存结果的变量已足够大,也并不意味着要产生结果的计算具有正确的类型。当你拿不准时,就使用long运算来执行整个运算。