web-dev-qa-db-ja.com

オーバーフローはJavaでどのように機能しますか?

オーバーフローについて読んだことがありますが、「オーバーフローとは、数値が大きすぎてデータ型に収まらない場合であるため、システムは次に小さい値に「ラップアラウンド」し、そこからカウントアップします」。

例えば:

short s = (short)1921222; // Stored as 20678

その例では、 -32768(Short.MIN_VALUE)しかし、別の整数データ型で証明しようとすると、同じように機能しないようです...

byte b = (byte)400; // Stored as -112

上記の例はからカウントを開始しました  それが私が見つけた唯一の方法でした -112

何か間違ったことをしているのかわかりません。

19
Luisk4

Java言語仕様 は次のように述べています。

整数型は、値がそれぞれ8ビット、16ビット、32ビット、64ビットの符号付き2の補数整数であるbyte、short、int、およびlongと、値が16ビットの符号なし整数であるcharです。 UTF-16コードユニットを表します。

したがって、shortbyteは両方とも 2の補数 整数です。

shortは16ビットです。つまり、2 ^ 16 = 65536の異なる値を保持できます。 65536番目の値の後、オーバーフローします。
1921222モジュロ65536は20678です。これは32768(2 ^ 15、2の補数のターニングポイント)未満であるため、正の数を維持します。

byteは8ビットです。つまり、2 ^ 8 = 256の異なる値を保持できます。これは256番目の値の後にオーバーフローします。 256を法とする400は144です。この値は、2の補数のターニングポイントである128よりも大きいため、負の2の補数として解釈されます。

17
S.L. Barth

キャストは数を切り捨てています。 ( [〜#〜] jls [〜#〜]

0000 0001 1001 0000

上位バイトを失って

1001 0000

これは-112です。

16
Kylos

Javaでは、byteプリミティブ型は8 bitsigned整数であるため、呼び出しから-112を取得しました。 :

byte b = (byte) 400;

次のように0xFFをバイナリで追加することで、これを回避して符号なしの値を取得できます。

int b = (byte) 400 & 0xFF;

詳細については、以下を確認できます。

6
cнŝdk

他の答えに加えて、手動計算によってもその答えを得ることができます。

Javaでは、データ型byteは8ビットの符号付き整数です。したがって、値は[-128, 127]の間隔にあります。 400の値があり、そのタイプの実際の値を確認したい場合は、間隔内の値に達するまで、その数値から間隔のsizeを引くことができます。 。

先ほど言ったように、byteは8ビットなので、間隔のサイズは256です。初期値からそれを引きます:400 - 256 = 144。この値はまだ間隔の外にあるため、もう一度減算する必要があります:144 - 256 = -112。この値は現在、間隔内にあり、実際にテストで確認した値です。

最初の例でも同じことが言えます。shortは16ビットで符号付きなので、間隔は[-32768, 32767]、サイズは65536です。値1921222から繰り返し減算を行うと、テストで見られるように、最終的に値20678が得られます。

3
QBrute