整數溢出問題
Java 中的 int 用 32 位表示,正數最大值的情況,首位是 0,其他位都可以是 1(就是 2^31-1)。但是如果正數過大了,例如 2^31,計算機不得不把首位變成 1,並且計算機不知道這是溢出情況,把它按照正常的方式輸出了,於是就成了負的。
2^31 - 1 = 0111 1111 1111 1111 1111 1111 1111 1111 = 2147483647
2^31 = 2^31 - 1 + 1 = 1000 0000 0000 0000 0000 0000 0000 0000 = -2147483648
演示1
public class Test { public static void main(String[] args) { int num = Integer.MAX_VALUE + 1; System.out.println(num); long longnum = Integer.MAX_VALUE + 1; //做加法前沒有對加數進行轉long型 System.out.println(longnum); } }
結果輸出的兩行都是-2147483648
解釋
做加法前,沒有將加數轉為long型,相加結果為 int 型,Integer.MAX_VALUE + 1 = -2147483648,將 -2147483648賦值給long型變量 longnum 后,longnum = -2147483648,這個很好理解,例如,將 int 型的數 -1賦值給 long 型,結果還是 -1;
演示2
public class Test { public static void main(String[] args) { int num = Integer.MAX_VALUE + 1; System.out.println(num); long longnum = Integer.MAX_VALUE + (long)1;//將一個加數轉為long型 System.out.println(longnum); } }
結果輸出第一行是 -2147483648,第二行是 2147483648
解釋
做加法前,將一個加數轉為 long 型,再做加法,由於 long 型可表示的最大數大於 2147483648,沒有發生溢出,將該值賦值給 long 型變量longnum,結果為 2147483648
應用
遞歸求 6 的階乘
public class Factorial { public static void main(String[] args) { System.out.println(fac(6)); }
//使用long作為返回值,遞歸到最后一次 return 1,返回時,1 被轉為 long 型,再依次相乘,結果為 long 型,考慮 int 型溢出
public static long fac(int n){ if(n>1) { return n * fac(n-1); }else { return 1; } } }