1. 程式人生 > 實用技巧 >Java中一個普通的迴圈為何從10開始到99連續相乘會得到0?

Java中一個普通的迴圈為何從10開始到99連續相乘會得到0?

這是一塊非常簡單的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