なぜ2の補数を使うのか
ビットで負の数を表現するときには、2の補数を用いて表現されることが多いです(これを2の補数表現といいます)。
なぜ2の補数表現が用いられるのか?
それは「マイナスの計算が簡単にできるから」です。
(2進数上で)2の補数で表現された負数は、以下のようにそのまま足すことでマイナスの計算ができます。
例: 5 - 4 をするとき
10進数の 5 → 2進数 0101
10進数の-4 → 2進数 1100 (2の補数表現を用いた場合)
0101 + 1100 = 10001
一番左の桁あふれは無視されるので、答えは0001 = 1
これから仕組みを説明していきます。
そもそも2の補数ってなに?
計算が簡単になる仕組みを説明する前に、まずはおさらいです。
すべてのビットを反転させた数が「1の補数」で、(例:101 の 1の補数 → 010)
すべてのビットを反転させて +1 をした数が「2の補数」 (例 101 の 2の補数 → 011)
と習うかもしれません。
が、これは「補数の求め方」であって、「定義」とはちょっと違う話になります。
定義を以下に説明します。
2の補数とは
補数とは、足すとちょうどその桁数を超えるような数のことをいいます。(1の補数ではなく2の補数の場合)
4桁の2進数で考えてみましょう。
ここに「1001」という数があるとします。この数になんの数を足すと、ちょうど桁が超える数...つまり「10000」になるでしょうか?
10000 - 1001 = 0111 ですね。これが「1001 に対する 2の補数」です。
これはビット反転 +1 でも求められます。
1001 をビット反転 → 0110 これに1を足すと、 0111。
4桁の10進数でも考えてみましょう。
「2進数で言う2の補数」というのは、10進数では「10の補数」と呼ばれます。
ここに「1234」という数があるとします。この数になんの数を足すと、ちょうど桁が超える数...つまり「10000」になるでしょうか?
10000 - 1234 = 8766 ですね。これが「1234 に対する 10の補数」です。
2進数とは違い、10の補数は引き算なしでは求められません。
2の補数で簡単にマイナスを計算できる仕組み
では、なぜ2の補数で簡単にマイナス計算ができるのでしょうか。
10進数で10の補数表現で計算してみる
まずは10進数で10の補数表現を用いてマイナスの計算をしてみましょう。
234 - 568 = -334 を考えます。
568 の 10の補数は 1000 - 568 = 432 です。これを234 に足してみましょう。
234 + (-568 +1000) = 234 + 432 = 666 です。
答えの-334 とは全然違う数になりましたね。なぜなら式を見ての通り+1000 を多く足しているからです。
なので最後に-1000をしてあげましょう。
234 - 568
= 234 + (-568 + 1000) - 1000 = 234 + 432 - 1000
= -334
正しい数になりました。結局のところ、補数を用いた計算は+1000をして再び-1000をしているだけです。
でもこれだと逆にややこしいですね。
-568+1000で結局引き算をしているからです。
2進数で2の補数表現を用いて計算してみる
2進数の場合は補数計算が楽なので簡単になります。
12 - 8 を2進数で考えます。
(10進数)12 → (2進数)01100
(10進数)8 → (2進数)01000
01000 の 2の補数は、10111 + 1 = 11000 です。
なので、
12 - 8
= 01100 - 01000
= 01100 + 11000 -100000 = 100100 - 100000 = 00100
01000の2の補数である11000は、100000 - 01000 をして求められた数なので、2足すと100000が多く足されます。だから最後に引く必要があります。
これが結局桁あふれになって、ビット計算では自動的に引かれることになるのです。