符号付き整数の負数と2の補数について理解したことのメモ。
※ここでは、「正の整数」は0も含むものとする。
8ビット符号付き整数を考えてみる。
まず8ビットで表現できる2進数は、0000 0000~1111 1111となる。
ただし最上位ビットは符号として扱う。
最上位ビット | 符号 |
---|---|
0 | 正 |
1 | 負 |
すると、表現可能な整数は以下のようになる。
正の整数 | 0000 0000~0111 1111 |
---|---|
負の整数 | 1000 0000~1111 1111 |
ここに10進数を対応させれば良い。
まずは正の整数。0はここに割り当てる。
2進数 | 0000 0000 | 0000 0001 | ~ | 0111 1111 |
---|---|---|---|---|
10進数 | 0 | 1 | ~ | 127 |
これは問題なさそう。
次は負の整数。
0は正の整数で表現したので、-1から割り当てる。
2進数 | 1000 0000 | 1000 0001 | ~ | 1111 1111 |
---|---|---|---|---|
10進数 | -1 | -2 | ~ | -128 |
これも問題なさそう...と最初は認識していた。(学び始めは!)
...実はこれ、問題がある。
一般的(?)な整数の演算を考えた場合、1 - 1 = 1 + (-1) = 0となるはず。
では、上記の整数表現で2進数を考えたらどうなるか。
10進数 | 1 + (-1) | = 0 |
---|---|---|
2進数 | 0000 0001 + 1000 0000 | = 1000 0001 |
2進数の計算結果が、明らかにおかしい...
10進数と2進数は表現の違いだけなので、2進数の計算結果も 0000 0000 になってほしい。
ここで、10進数と2進数の対応を見直す。
負の整数表現を修正する。
計算結果が 0000 0000 (10進数の0) になるためには、どのような値を加算すればよいのか。
まずは、次の計算を考えてみる。
1111 1111 + 0000 0001 = 1 0000 0000
『計算結果を見ると、1のビットがある。10進数の0では無さそうだ...』
と、考えるのは待ってほしい。
もともと8ビットの世界で進めていた話だ。
9ビット目は認識できない世界なので、無視しよう!!
改めて、計算は以下のようになる。
1111 1111 + 0000 0001 = 0000 0000
結果が0になった。嬉しい!!!
これを利用すると、負の整数は以下のように対応させれば良さそうだ。
2進数 | 1000 0000 | 1000 0001 | ~ | 1111 1111 |
---|---|---|---|---|
10進数 | -128 | -127 | ~ | -1 |
(検算1)
127 - 127
= 127 + (-127)
= 0111 1111 + 1000 0001
= 0111 1111 + 1000 0000 + 0000 0001
= 1111 1111 + 0000 0001
= 0000 0000
(検算2)
56 -56
= 56 + (-56)
= 0011 1000 + 1100 1000
= 0011 1000 + 1100 0111 + 0000 0001
= 1111 1111 + 0000 0001
= 0000 0000
確かに問題ない。
正と負の関係を考えてみる。
負の整数を2進数で表すことはできた。
10進数で言うところの、マイナス倍はどのように捉えればよいか。
例えば 56 * (-1) = -56 のように、符号だけ付け替えること。
検算をよく観察すると、以下のように考えれば良さそうだ。
127を-127にする。
(127=) 0111 1111 →(ビット反転)→ 1000 0000 →(1加算)→ 1000 0001 (= -127)
56を-56にする。
(56 =) 0011 1000 →(ビット反転)→ 1100 0111 →(1加算)→ 1100 1000 (= -56)
操作の目的は、元の値に加算すると 0000 0000 になる値へ変換すること。
- ビット反転後は、元の値に加算すると 1111 1111 となる。
- さらに1を加えた値は、元の値に加算すると 0000 0000 となる。
この操作で問題なさそうだ。
ちなみに、負の整数を正の整数にも変換できる。
(-76=)1011 0100 →(ビット反転)→ 0100 1011 →(1加算)→ 0100 1100 (= 76)
つまり、2進数のマイナス倍は「ビット反転して1加算」で操作できる!!!
2の補数
このビット反転で得られた値には、名前がある。
操作 | 得られる値の名前 |
---|---|
整数Aをビット反転 | Aの1の補数 |
整数Aをビット反転して1加算 | Aの2の補数 |
負の整数は、正の整数の2の補数を考えれば良いということになる。
なるほど~
ちなみに、ビット反転で解決することは、コンピュータ的には簡単で嬉しいらしい。
(電気信号のON↔OFFを変えれば済むので。)
つぶやき
整数について勉強したときに「なんで負の整数は2の補数なんや!!!」と思いつつ、放置してた。
なんとなく考えてたら分かってきたので、備忘録として書いた。
鍵は、「足して0にする。」という考え方だと思う。
雰囲気としては、群論の逆元の概念で理解したつもり。