web-dev-qa-db-ja.com

なぜInteger.MAX_VALUE + 1 == Integer.MIN_VALUEなのですか?

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

本当です。

Javaの整数は32ビットであり、2を超えることはできません。31-1ですが、MAX_VALUEに1を追加すると、何らかの例外ではなくMIN_VALUEが発生する理由を理解できません。 Rubyのように、より大きな型への透過的な変換のようなものについては触れません。

この動作はどこかに指定されていますか?信頼できますか?

27
Oleg Mikheev

整数がオーバーフローするためです。オーバーフローした場合、次の値はInteger.MIN_VALUE関連するJLS

整数の加算がオーバーフローする場合、結果は、いくつかの十分に大きな2の補数形式で表される数学的合計の下位ビットになります。オーバーフローが発生した場合、結果の符号は、2つのオペランド値の数学的合計の符号と同じではありません。

28
Bozho

整数ストレージがオーバーフローし、 JSL 3 rd Ed。で述べられているように、これはまったく示されていません

組み込みの整数演算子は、オーバーフローやアンダーフローを示すものではありません。 unboxing変換 (§5.1.8) null参照が必要な場合、整数演算子はNullPointerExceptionをスローできます。それ以外では、例外をスローできる唯一の整数演算子 (§11) は整数除算演算子/(§15.17.2) および整数剰余演算子%(§15.17.3) 、右側のオペランドがゼロの場合はArithmeticExceptionをスローし、インクリメントおよびデクリメント演算子++§15.15.1§15.15.2 )および--§15.14.§15.14.2 )、ボクシング変換の場合はOutOfMemoryErrorをスローできます (§5.1.7 ) が必要であり、変換を実行するのに十分なメモリがない。

4ビットストレージの例:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)

MAX_INT + 1:

 0111+
 0001
 ----
 1000
25
falsarella

整数値がバイナリ形式でどのように表されるか、およびバイナリ加算がどのように機能するかを理解する必要があります。 Javaは、数値の最初のビットが符号を表す2の補数と呼ばれる表現を使用します。最大のものに1を追加するときは常にJava Integer、ビット符号が0の場合、そのビット符号は1になり、数値は負になります。

このリンクは詳細を説明しています: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-Java

-

Java言語仕様はこの動作をここで扱います: http://docs.Oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

整数の加算がオーバーフローする場合、結果は、いくつかの十分に大きな2の補数形式で表される数学的合計の下位ビットになります。オーバーフローが発生した場合、結果の符号は、2つのオペランド値の数学的合計の符号と同じではありません。

これは、この動作に依存できることを意味します。

8
ARRG

ほとんどのプロセッサでは、算術命令にはオーバーフローでフォールトするモードがありません。チェックする必要があるフラグを設定します。これは追加の指示なので、おそらく遅くなります。言語の実装を可能な限り高速にするために、エラーを無視して続行するように言語が頻繁に指定されています。 Javaの場合、動作は [〜#〜] jls [〜#〜] で指定されます。Cの場合、言語は動作を指定しませんが、最新のプロセッサJavaとして動作します。

(ぎこちない)Java SE 8ライブラリがオーバーフローをスローするように提案しているだけでなく、署名されていない操作もあると思います。DSPの世界で人気のある動作は、最大値なので、Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [Java以外]。

将来の言語では任意の精度のintが使用されると確信していますが、しばらくはそうではありません。高速に実行するには、より高価なコンパイラー設計が必要です。

国際日付変更線を越えると日付が変わるのと同じ理由:そこに不連続があります。バイナリ加算の性質に組み込まれています。

4
duffymo

これは、整数がバイナリレイヤーで 2の補数 として表されるという事実に関連するよく知られた問題です。 2の補数の最大値に1を加えると、最小値が得られます。正直なところ、すべての整数はJavaが存在する前にこのように動作しました。Java言語のこの動作を変更すると、整数計算にオーバーヘッドが追加され、プログラマーが混乱します他の言語から。

4
Craig H