簡単にするために、8 ビット整数を使用します。
バイナリでは、8 ビットの範囲は00000000b
~11111111b
です。
00000000b = 0d
11111111b = 255d
では、コンピューターはどのようにして整数に符号を追加するのでしょうか? 2の補数です。
符号なし整数の場合、次の方法11111111b
でバイナリからデナリーに変換します。
11111111b
= 1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
= 1*128 + 1*64 + 1*32 + 1*16 + 1*8 + 1*4 + 1*2 + 1*1
= 255d
では、符号付き整数は11111111b
どうですか? 簡単な方法は次のとおりです。
v----------(sign flag 1=negative)
11111111b
= 1*(-2^7) + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
= 1*(-128) + 1*64 + 1*32 + 1*16 + 1*8 + 1*4 + 1*2 + 1*1
= -1d
一般に、符号付き数値の最上位ビットは符号フラグです。
負のデナリー数を 2 の補数に変換するには:
-18d
========
without sign 0001 0010
one's complement 1110 1101 (inverted)
*two's complement 1110 1110 (one's complement + 1)
8 ビットの符号付き整数の範囲は-2^7
~2^7-1
です。
オーバーフローとは何ですか?どれどれ:
01111111b
= 127d
01111111b + 1
= 10000000b
= 1*(-2^7) + 0*2^6 + 0*2^5 + 0*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 0*2^0
= 1*(-128) + 0*64 + 0*32 + 0*16 + 0*8 + 0*4 + 0*2 + 0*1
= -128d
127d + 1d
=========
0111 1111 (127d) +
+0000 0001 (1d) +
----------
1000 0000 (-128d) - (overflow)
したがって、最大の 8 ビット符号付き整数に 1 を加算すると、結果は最小の 8 ビット符号付き整数になります。+ve + +ve -> -ve はオーバーフロー エラーです。
引き算はどうですか?45-16? (+ve + -ve -> +ve)
45d - 16d
=========
0010 1101 (45d) +
+1111 0000 (-16d) -
----------
1 0001 1101 (29d) +
^---------------------(discard)
45-64はどうですか?(+ve + -ve -> -ve)
45d - 64d
=========
0010 1101 (45d) +
+1100 0000 (-64d) -
----------
1110 1101 (-19d) -
-64-64はどうですか?(-ve + -ve -> -ve)
-64d - 65d
=========
1100 0000 (-64d) -
+1100 0000 (-64d) -
----------
1 1000 0000 (-128d) +
^---------------------(discard)
-64-65はどうですか?
-64d - 65d
=========
1100 0000 (-64d) -
+1011 1111 (-65d) -
----------
1 0111 1111 (127d) + (underflow)
^---------------------(discard)
したがって、 -ve + -ve -> +ve はアンダーフロー エラーです。
状況は 32 ビット整数の場合と似ていますが、より多くのビットが利用可能です。
あなたの質問について2*1500000000
、それらを 32 ビットの符号なし整数として扱うと、結果は次のように3000000000
なり、そのバイナリ表現は次のようになります。
1011 0010 1101 0000 0101 1110 0000 0000
= 1*2^31 + 0*2^30 + ...
= 1*2147483648 + 0*1073741824 + ...
= 3000000000d
しかし、それを 32 ビットの符号付き整数として扱うと、次のようになります。
v------(Let's recall this is the sign flag)
1011 0010 1101 0000 0101 1110 0000 0000
= 1*(-2^31) + 0*2^30 + ...
= 1*(-2147483648) + 0*1073741824 + ...
= -1294967296d
追加:符号なし整数のオーバーフロー
符号なし整数のオーバーフローは非常に似ています。
11111111b
= 255d
11111111b + 1
= 00000000b
= 0d
255d + 1d
=========
1111 1111 (255d) +
+0000 0001 (1d) +
----------
1 0000 0000 (0d) - (overflow)
^---------------------(discard)
そのため、32 ビット符号なし整数の場合は常にmod 2^32
.
ところで、これは Java だけでなく、C/C++ などのほとんどのプログラミング言語でも同様です。PHP/JavaScript のように、他のプログラミング言語の中には、オーバーフローを自動的に処理し、型をより高い精度または浮動小数点に変更するものがあります。