なにを当たり前のことを…とお思いかもしれませんが、これがなかなか腑に落ちなかったのです。
だって、絶対値が大きいほうが、負の数は小さくなるじゃないですか。
(0111)2 が7なら、符号ビット入れ替えて(1111)2 にしたら、-7になりそうじゃないですか。
これが、実際のところは-1になるとか、普段の感覚からは飛躍しすぎなのです。
まあ、ようするに補数表現が理解できてなかったんですよね。
コンピュータのビット演算には桁あふれというものがある
計算可能なビット列の範囲からあふれた値が消えるということを実感できれば、簡単なことでした。
っていうか、2進数の加算、減算をいくつかプログラム書いて実際に動かしているうちに、「2つの符号付き2進数を足して0になる」とはどういうことか実感できたということなのですが。
(0100)2 は、符号付き2進数で4を表します。4に何を足したら0になるかというと、もちろん-4です。
では、-4は符号付き2進数でどう表されるでしょうか。
(0100)2 との演算結果が (0000)2 になればいい、ということです。
加算して桁あふれさせることで(0000)2 になる値が、-4を表しているということです。
ビット反転して1足して、、、(1100)2 。これが符号付き2進数での「-4」です。
bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | |
0 | 1 | 0 | 0 | ||
+ | 1 | 1 | 0 | 0 | |
= | 0 | 0 | 0 | 0 |
4 = (0100)2 に-4 = (1100)2 を加算してみたら、桁あふれして0になりました。
これは、普通の10進数での計算の感覚である 4 + (-4) = 0と一致します。
ああすっきり。めでたしめでたし。
もう一つの考え方:0から1引いたらどうなるか
上記のほかにもう一つ発見をしました。
(0011)2 これは2進数表記の3です。ここから1引いたら(0010)2 、さらに1引いたら(0001)2 になります。ここまでは普通の感覚と同じです。
(0000)2 は0ですね。ここからさらに1ひいて、-1になるときはどうでしょうか。
これは、桁下がりと同じ考え方でよいのです。100から1引いたら、99になりますね。
桁下がりによって下の桁の数字は大きくなります。
2進数でも同じです。(0000)2 から-1引いたら、(架空の)5桁目から桁下がりしてきたと考えます。
というわけで、 0 = (0000)2 から1を引いた結果である -1は、 (1111)2 なのです。
ここからさらに1を引くと、 -2 = (1110)2 となります。
順番に1を引いていって、 (1000)2 が、4ビットの符号つき整数で表現できる最小値である -8 となります。
(0000)2 | 0 |
(1111)2 | -1 |
(1110)2 | -2 |
(1101)2 | -3 |
(1100)2 | -4 |
(1011)2 | -5 |
(1010)2 | -6 |
(1001)2 | -7 |
(1000)2 | -8 |
これは、ビットの桁数がいくつでも変わりません。
符号付き2進数のすべての桁が1のときは、常に-1です。
そして、最上位ビット(符号ビット)だけ1のときが、表現可能な範囲での最小値になります。
屁理屈っぽいですが、そういうことなのです。
あなたのお役に立てれば嬉しいです。