System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);
本当です。
Javaの整数は32ビットであり、2 31 -1を超えることはできないことは理解していますが、ある種の例外ではなく、MAX_VALUE
結果に1を追加する理由を理解できません。MIN_VALUE
Rubyのように、より大きなタイプへの透過的な変換のようなものについては言及していません。
この動作はどこかで指定されていますか?頼りにできますか?
System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);
本当です。
Javaの整数は32ビットであり、2 31 -1を超えることはできないことは理解していますが、ある種の例外ではなく、MAX_VALUE
結果に1を追加する理由を理解できません。MIN_VALUE
Rubyのように、より大きなタイプへの透過的な変換のようなものについては言及していません。
この動作はどこかで指定されていますか?頼りにできますか?
整数がオーバーフローするためです。オーバーフローすると、次の値は。になりInteger.MIN_VALUE
ます。関連するJLS
整数の加算がオーバーフローした場合、結果は、十分に大きい2の補数形式で表される数学的合計の下位ビットになります。オーバーフローが発生した場合、結果の符号は2つのオペランド値の数学的合計の符号と同じではありません。
JSL 3rd Edで述べられているように、整数ストレージがオーバーフローし、それはまったく示されません。:
組み込みの整数演算子は、オーバーフローまたはアンダーフローを示すものではありません。整数演算子は、null参照のボックス化解除
NullPointerException
変換(§5.1.8)が必要な場合にスローできます。それ以外に、例外(§11)をスローできる整数演算子は、整数除算演算子/
(§15.17.2)と整数剰余演算子%
(§15.17.3)だけです。これらArithmeticException
は、右側のオペランドがゼロ、およびインクリメント演算子とデクリメント演算子++
(§15.15.1、§15.15.2)および--
(§15.14.3、§15.14.2OutOfMemoryError
)。これらはifボクシング変換(§5.1.7)をスローできます。が必要であり、変換を実行するために使用できる十分なメモリがありません。
4ビットストレージの例:
MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)
MAX_INT + 1:
0111+
0001
----
1000
整数値が2進形式でどのように表されるか、および2進加算がどのように機能するかを理解する必要があります。Javaは、2の補数と呼ばれる表現を使用します。この表現では、数値の最初のビットがその符号を表します。ビット符号が0の最大のJava整数に1を加算すると、そのビット符号は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つのオペランド値の数学的合計の符号と同じではありません。
これは、この動作に依存できることを意味します。
ほとんどのプロセッサでは、算術命令にはオーバーフロー時にフォールトするモードがありません。チェックする必要のあるフラグを設定します。これは余分な指示なので、おそらく遅くなります。言語の実装をできるだけ速くするために、エラーを無視して続行するように言語が頻繁に指定されます。Javaの場合、動作はJLSで指定されます。Cの場合、言語は動作を指定しませんが、最新のプロセッサはJavaとして動作します。
署名されていない操作だけでなく、オーバーフローをスローする(厄介な)JavaSE8ライブラリの提案があると思います。DSPの世界で人気のある動作は、値を最大にクランプすることです。つまり、Integer.MAX_VALUE + 1 == Integer.MAX_VALUE
[Javaではありません]。
将来の言語では任意精度のintが使用されると確信していますが、まだしばらくは使用されていません。迅速に実行するには、より高価なコンパイラ設計が必要です。
日付変更線を越えると日付が変わるのと同じ理由:そこには不連続性があります。これは、バイナリ加算の性質に組み込まれています。
これは、整数が2の補数としてバイナリ層で表されるという事実に関連するよく知られた問題です。2の補数の最大値に1を加算すると、最小値が得られます。正直なところ、Javaが存在する前はすべての整数がこのように動作し、Java言語でこの動作を変更すると、整数演算のオーバーヘッドが増え、他の言語のプログラマーが混乱することになります。
(binaryで)1(3
binaryで)に追加するときは、0になるまで、右から始めて(binaryで)すべてのbinaryに変更する必要があります。これをに変更する必要があります。すべての場所がいっぱいになっているので、sだけが残ります。11
1
0
0
1
1
Integer.MAX_VALUE
1
0
byte a=127;//max value for byte
byte b=1;
byte c=(byte) (a+b);//assigns -128
System.out.println(c);//prints -128
ここでは、加算を強制し、バイトとして扱われるようにキャストしています。したがって、127(1バイトの可能な最大値)に到達し、プラス1を加算すると、値は127から(画像に示されているように)反転し、-128になります。値はタイプの周りを回り始めます。
整数についても同様です。
また、整数+整数は整数のままです( [上記のように強制的にキャストされない限り]intに変換されるバイト+バイトとは異なります)。
int int1=Integer.MAX_VALUE+1;
System.out.println(int1); //prints -2147483648
System.out.println(Integer.MIN_VALUE); //prints -2147483648
//below prints 128 as converted to int as not forced with casting
System.out.println(Byte.MAX_VALUE+1);
原因オーバーフローと2準拠の性質カウントは「2番目のループ」になり、最も右の位置2147483647にあり、1を合計した後、最も左の位置-2147483648に現れ、次の増分は-2147483647、-2147483646、-2147483645になります。 ...など、このビット深度での加算マシンの性質を何度も何度も繰り返します。
いくつかの例:
int a = 2147483647;
System.out.println(a);
与える:2147483647
System.out.println(a+1);
-2147483648(オーバーフローと2準拠の性質カウントが「2番目のループ」になるため、右端の位置2147483647にあり、1を合計した後、左端の位置-2147483648に表示され、次の増分は-2147483648になります。 2147483647、-2147483646、...など、このビット深度での加算マシンの性質を何度も何度も繰り返します)
System.out.println(2-a);
与える:-2147483645(-2147483647 + 2は数理論理学のようです)
System.out.println(-2-a);
与える:2147483647(-2147483647-1-> -2147483648、-2147483648-1-> 2147483647前の回答で説明されているループ)
System.out.println(2*a);
与える:-2(2147483647 + 2147483647-> -2147483648 + 2147483646再び数理論理学)
System.out.println(4*a);
与える:-4(2147483647 + 2147483647 + 2147483647 + 2147483647-> -2147483648 + 2147483646 + 2147483647 + 2147483647-> -2-2(最後の回答による)-> -4) `