Hatena::ブログ(Diary)

とあるソフトウェア開発者のブログ RSSフィード

2010-08-24

2の補数を理解する (1)

昔、2の補数を理解できずに悩んだのを思い出したので、2の補数について書いてみたいと思います。

次回: id:simply-k:20100825:1282743815

1の補数と2の補数

1の補数

2の補数を理解する準備として、1の補数について説明します。ある数Aに対する1の補数とは、次のような条件を満たす数のことです。「『A』の2進表現と『Aの1の補数』の2進表現を加算すると、計算結果の全てのビットが1になる。」

例えば、Aの2進表現(8ビット)が01011100だった場合、Aの1の補数の2進表現は、10100011となります。(01011100 + 10100011 = 11111111) 例を見ればすぐにわかるように、Aの1の補数は、Aの2進表現ビット反転させたものになります。「オール1にするために補う数」なので、「1の補数」と呼ばれます。

2の補数

ある数Aに対する2の補数とは、次のような条件を満たす数のことです。「『A』の2進表現と『Aの2の補数』の2進表現を加算すると、計算結果は2nになる。(nはAのビット数)」

例えば、Aの2進表現(8ビット)が01011100だった場合、Aの2の補数の2進表現は、10100100となります。(01011100 + 10100100 = 100000000 = 28) 定義からすぐにわかるように、Aの2の補数は、Aの1の補数に1を足した値となります。1の補数はビット反転で計算できるため、2の補数は「ビット反転+1」で計算できることになります。「2nにするために補う数」なので、「2の補数」と呼ばれます。

1の補数と2の補数についての補足

1の補数や2の補数を考える場合、その数が何ビット表現されるのかを意識する必要があります。例えば、10進数の5(2進数の101)に対する1の補数は、次のようになります。

  • 数値が4ビット表現される場合は、0101をビット反転するので、1の補数は1010となる。
  • 数値が8ビット表現される場合は、00000101をビット反転するので、1の補数は11111010となる。
  • 数値が16ビット表現される場合は、0000000000000101をビット反転するので、1の補数は1111111111111010となる。

また、補数の定義から明らかなように、ある数の補数の補数は、元の数と一致します。つまり、次のような命題が成り足ります。

  • ある数Aに対し、Aの「1の補数」の「1の補数」はAである。
  • ある数Aに対し、Aの「2の補数」の「2の補数」はAである。
その他の補数

上記では2進数に関する補数を説明しましたが、それ以外の場合にも補数を考えることは可能です。例えば、10進数に対して、9の補数や10の補数を考えることが可能です。Aを4桁の10進数とします。ここで、Aの値が2345だったとすると、Aの9の補数は7654となります。(2345 + 7654 = 9999) また、Aの10の補数は7655となります。(2345 + 7655 = 10000 = 104)

符号付き整数と2の補数

符号付き整数を2の補数によって表現する

現在の一般的なコンピュータ環境では、符号付き整数を表現するために2の補数を利用します。2の補数を用いた符号付き整数の表現には、次のようなルールがあります。

  • 最上位ビットが1の場合は負の数、それ以外は0または正の数を表現する。
  • 負の数は、絶対値の2進表現の2の補数によって表現される。

これだけでは理解しにくいと思いますので、4ビットの場合について、表にしてみます。

2進表現10進表現
(符号無し)
10進表現
(符号付き)
111115-1
111014-2
110113-3
110012-4
101111-5
101010-6
10019-7
10008-8
011177
011066
010155
010044
001133
001022
000111
000000

最上位ビットが1の数は、符号無しの場合には、表現可能な整数の中の大きい方の半分を表現します。しかし、符号付きの場合には、負の数を表現します。

2進表現での2の補数を計算することは、10進表現(符号付き)で符号を反転することに相当します。例えば、10進数の3と-3は2進数ではそれぞれ0011と1101ですが、ここで次のような対応が存在します。

  • 3 ← 符号を反転 → -3 (10進表現)
  • 0011 ← 2の補数を計算 → 1101 (2進表現)
2進表現から10進表現(符号付き)を求める方法

2進表現から10進表現(符号付き)を求める場合は、以下のようにして考えます。

  • 最上位ビットが0の場合は、単純に2進数を10進数に変換する。
    (例: 0110 → 6)
  • 最上位ビットが1の場合は、2の補数を10進数に変換し、符号としてマイナスを付ける。
    (例: 1100の2の補数は0100であり、「0100 → 4」である。つまり、「1100 → -4」である。)

最上位ビットが1の場合の計算では、ある数-Aの2進表現の2の補数がAになることを利用しています。

10進表現(符号付き)から2進表現を求める方法

10進表現(符号付き)から2進表現を求める場合は、以下のようにして考えます。

  • 0または正の数の場合は、単純に10進数を2進数に変換する。
    (例: 5 → 0101)
  • 負の数の場合は、絶対値の2進表現の2の補数に変換する。
    (例: -3の絶対値は3であり、「3 → 0011」である。0011の2の補数は1101なので、「-3 → 1101」である。)
表現可能な範囲

符号付き整数を2の補数によって表現する場合、表現可能な整数の範囲は、-(2n-1)〜2n-1-1(nはビット数)となります。例えば、8ビット整数の場合、表現可能な最小値は-128(-27)、最大値は127(27 - 1)となります。最大値の絶対値は、最小値の絶対値よりも1小さくなります。(最上位ビットが0の範囲に0が含まれるため)

補足

符号付き整数を2の補数によって表現する場合、次のような特徴があります。


次回は、2の補数を利用した整数の加算について説明します。

次回: id:simply-k:20100825:1282743815

danboodanboo 2015/12/02 09:35 分かりやすかったです。ありがとうございます。

danboodanboo 2015/12/02 09:35 分かりやすかったです。ありがとうございます。

benkbenk 2016/05/22 09:03 とても整理されていて、解りやすいです。ありがとうございます。

とある壮年とある壮年 2016/08/11 22:55 有り難うございます。必要があって「コンピュータ概論」を学んでいるのですが、テキストが非常に不親切で分かりにくかったのですが、とても良く分かりました。
ありがとうございました。

kedamakedama 2016/10/08 04:57 要点がまとめられていて、とても分かりやすかったです。
ありがとうございます。

あ 2017/01/20 14:07 「要点からすぐに」にイラっとくる

あ 2017/01/20 14:07 「要点からすぐに」にイラっとくる

kkkk 2017/02/26 13:00 大変参考になりました。ありがとうございます。

kkkk 2017/02/26 13:00 大変参考になりました。ありがとうございます。

kkkkkk 2017/04/14 16:07 非常にわかりやすく、理解の手助けになりました。
ありがとうございました。

mm 2017/09/28 16:15 こちらの記事を拝見して、やっとわかりました。ありがとうございます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証