10から99まで連続的に乗算すると、Javaの通常のループが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ビットの符号付き2の補数型であることを覚えておいてください(翻訳者注:64はjdkでも同じです)。これは、コンピューター内で乗算の各ステップが行うことです。

ここに画像の説明を挿入 ラベル(1)は実際の10進数の結果です。

マーク(2)16進および10進法の内部表現結果int型は、データの下位32ビットのみを格納します。

ラベル(3)はラベル(2)の補足です。

0がどこから来るのか知りたい場合は、上記のバイナリ表現の結果を詳しく見てください。注意深い学生は気づくでしょう:

任意の数に偶数を掛けると、偶数になります。

偶数と偶数を乗算すると、全体として2進数が左にシフトし、0は右からスペースを埋めます。

偶数と奇数を乗算しても、右端のゼロの数は変わりません。

乗算が十分に行われると、右側に0ビットが増えます。最後に、積が継続的に42に乗算されると、積のバイナリ表現の下位32ビットはすべて0になるため、intは0になります。

問題の拡張

これで問題の原因がわかったので、別の変数を使用して、バイトを例として、同じ操作を実行できます。

Javaのバイト変数は8ビットの符号付き数値であり、これも1の補数で表されます。上記の結果表から、10から16に連続的に乗算すると、バイナリ結果の下位8ビットがすべて0になるため、このときのバイト変数は0であることがわかります。15に乗算すると、下位8ビットは10010000になります。補数から元のコードを見つける方法を覚えていますか?非常に単純です。符号ビットは変更されず、他のビットは反転されて1が追加され、11110000(-112)になります。興味がある場合は、マシンで結果を確認してください。興味のある学生は、テクニカルディスカッショングループに参加できます:626267345ファイル

おすすめ

転載: blog.csdn.net/weixin_46577306/article/details/108285637