這是一塊非常簡單的Java代碼片段:
public class HelloWorld{
public static void main(String []args){
int product = 1;
for (int i = 10; i <= 99; i++) {
product *= i;
}
System.out.println(product);
}
}
為什么得出的結果是0呢?
問題現象
蛋疼的同學可能會發現這個程式執行的規律:
1 * 10 = 10
10 * 11 = 110
110 * 12 = 1320
1320 * 13 = 17160
17160 * 14 = 240240
240240 * 15 = 3603600
3603600 * 16 = 57657600
57657600 * 17 = 980179200
……
-1342177280 * 40 = -2147483648
-2147483648 * 41 = -2147483648
-2147483648 * 42 = 0
0 * 43 = 0
0 * 44 = 0
……
0 * 97 = 0
0 * 98 = 0
程式從42開始就已經輸出0,所以42以后的數字相乘的結果就顯而易見了,從結果中發現,乘積的符號已一種難以理解的方式變換著,表明乘積已經溢位了,同時也說明Java并不會理會整數的上下溢位,
問題解答
請記住Java的int型別是32位的有符號二進制補碼表示的數字型別(譯者注:64為jdk同樣如此),這是每一步乘法在計算機內部所做的操作:

標注(1)是實際十進制結果,
標注(2)十六進制以及十進制的內部表示結果,int型別只會存盤低32位的資料,
標注(3)是標注(2)的補碼形式,
如果你好奇0從哪里來,請仔細看上方2進制表示的結果,細心的同學會注意到:
任何一個數與偶數相乘得偶數,
偶數與偶數相乘,會將2進制位整體左移,0從右邊填補空位,
偶數與奇數相乘,不會改變最右方0的數量,
當乘法執行的足夠多次時,右方的0位會越來越多,最終,連續乘到42時,乘積的2進制表示的低32位全是0,所以int將會是0,
問題擴展
既然知道了問題的原因,我們換一種變數來做同樣的操作,以byte為例,
Java的byte變數是8位的有符號數,同樣也是補碼表示,從上方結果表格看出,連續從10乘到16時,2進制結果的低8位全都是0,所以此時的byte變數是0,而連續乘到15時,低8位是10010000,還記得怎么由補碼求原碼嗎?很簡單, 符號位不變,其余位取反加1,得出11110000,既-112,感興趣的朋友請在自己機器上驗證結果,有興趣的同學可以加入技術討論群:626267345

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/38593.html
標籤:Java
上一篇:阿里技術官分享內部SpringCloud微服務實戰筆記,不得不愛
下一篇:Java比較器:Comparator介面與Comparable介面的compare(compareTo)方法回傳值的正負與升序、降序的關系
