補数とは何か

1. 補数とは何か

 補数(complement)とは、ある数値に特定の数を加えると、桁上がりが発生するような数のことを指します。​例えば、10進数で「3」に対する補数は「7」であり、これらを足すと「10」となり、一桁上がります。​同様に、2進数で「011」に対する補数は「101」で、これらを足すと「1000」となり、桁上がりが生じます。​

 補数には、基数の補数(radix complement)と減基数の補数(diminished radix complement)の2種類があります。​基数の補数は、与えられた数を基数のべき乗から引いた値で、減基数の補数は、基数のべき乗から1を引いた値から与えられた数を引いた値です。​

1.1. JISの定義を確認する

 補数(と関係する数)の定義についてJISで確認してみましょう。

 補数(complement)は、「与えられた数を、ある決められた数から引くことによって得られる数」(JIS X0005)です。

 基数の補数(radix complement)は、「与えられた数を、基数のある決められたべき乗から引くことによって得られる補数」(JIS X0005)です。

 減基数の補数(diminished radix complement)は、「与えられた数を、基数のある決められたべき乗より1小さい数から引くことによって得られる補数」(JIS X0005)です。

2. 補数を式で表す

2.1. b進法

 \(b\)進法で\(n\)桁の数字\(x\)の補数を考えます。

 補数\(y\)は、定義にしたがって\(y = b^n – x\)となります。

 減基数の補数\(z\)は、\(z = ( b^n – 1 ) – x\)となります。

2.2. 10進法

 より具体的に10進法の場合で考えてみます。

2.2.1. 10の補数

 10進法で3桁の数字321の補数を考えます。

 補数は、\(y = 10^3 – 321 = 679\)

 これは基数の補数ですので、321の10(10が基数)の補数となります。

 基数の補数ですので、\(679 + 321 = 1000 = 10^3\)で、定義どおりだと確認できました。

2.2.2. 9の補数

 減基数の補数は、\(z = ( 10^3 – 1 ) – 321 = 678\)

 これは減基数の補数ですので、321の9(10の減基数)の補数となります。

 減基数の補数ですので\(678 + 321 = 999 = 1000 – 1 = 10^3 – 1\)で、定義どおりです。

2.3. 2進法

2.3.1. 2の補数

 2進法で3桁の数字111の補数を考えます。

 補数は、\(y = 2^3 – 111 = 1\)

 これは基数の補数ですので111の2(2が基数)の補数となります。

 基数の補数ですので、\(1 + 111 = 1000 = 2^3\)で、定義どおりだと確認できました。

2.3.2. 1の補数

 減基数の補数は、\(z = ( 2^3 – 1 ) – 111 = 0\)

 これは減基数の補数ですので、321の1(2の減基数)の補数となります。

 減基数の補数ですので\(0 + 111 = 111 = 1000 – 1 = 2^3 – 1\)で、定義どおりです。

3. 1の補数と2の補数

 コンピュータで計算する場合、32bitや64bitという2進法で表現された2進数を用いて計算します。

 この2進数は、論理演算という計算方法と親和性が良いためコンピュータには欠かせないものです。

 そこで先にみてきた2進法での補数である1の補数と2の補数について見ていきましょう。

3.1. 1の補数の特徴

 まず、1の補数がどのようなものか4bitの場合で見ていきます。

2進数10進数1の補数1の補数の10進数
000001111-0
000111110-1
001021101-2
001131100-3
010041011-4
010151010-5
011061001-6
011171000-7
1000801117
1001901106
10101001015
10111101004
11001200113
11011300102
11101400011
11111500000
4ビットの2進数とその1の補数、およびそれに対応する10進数の値

 この表を見てわかるとおり、1の補数をとるというのは、各ビットを反転させることと同じです。そのためコンピュータで計算するのは高速に行えます。(ビット毎のnotをとる)

 しかし、1の補数では0は0000と11111の2つの表現やキャリーオーバーの課題があり、使い場所は多くありません。

3.1.1. 1の補数のキャリーオーバーの例

 先の4bitの数値で計算してみます。

 A:1101(10進数の2)

 B:1011(10進数の4)

 これらを加算します。

 1101 + 1011 = 1 1000

 これは、キャリーオーバー:1、結果:1000という意味になります。

 これを正しい結果にするためにはキャリーオーバーした1を最下位ビットに加える必要があります。

 1000 + 0001 = 1001

 この処理をおこなう必要があるため1の補数はあまり多くの場所では使われていません。

3.1.2. 1の補数の活用例

 1の補数は、エラー検出のためのチェックサム計算に使用されることがあります。

 Internet Protocol (IP) バージョン4のヘッダチェックサムは、1の補数の加算と1の補数を使用して計算されます。このチェックサムは、IPヘッダのエラーを検出するために使用されます。もしチェックサムが一致しなければ、パケットは破棄されます。

3.2. 2の補数の特徴

2進数10進数2の補数2の補数の10進数
0000000000
000111111-1
001021110-2
001131101-3
010041100-4
010151011-5
011061010-6
011171001-7
100081000-8
1001901117
10101001106
10111101015
11001201004
11011300113
11101400102
11111500011
4ビットの2進数とその1の補数、およびそれに対応する10進数の値

 この表を見てわかるとおり、2の補数では、1の補数+1となっています。各ビットを反転させてから最下位ビットに1を加えています。そのため0は0000一つになり、加算や減算がシンプルになっています。

3.3. 2の補数が有効である理由

 2の補数がコンピュータで広く使用されている主な理由は以下の通りです。

  1. 加減算の統一化:​2の補数を用いることで、減算を加算として処理できます。これは、ハードウェア上で減算器を設計する必要がなく、加算器だけで済むため、回路設計が簡素化されます。 ​
  1. 0の一意性:​1の補数では「+0」と「-0」の2つの0が存在しますが、2の補数では0の表現が1つだけで済みます。これにより、計算処理がより効率的かつ正確になります。
  2. オーバーフローの検出:​2の補数表現では、演算中に桁あふれ(オーバーフロー)が発生した場合、符号ビットの変化として検出しやすくなります。これにより、エラーの検出と処理が容易になります。

3.4. 2の補数の導出方法

 この2段階の方法により2の補数は導出できます。

4. 参考文献

  1. JIS X 0005:2002 情報処理用語(データの表現) | 日本規格協会 JSA Group Webdesk
  1. The Art of Computer Programming Volume 2… – アスキードワンゴ