2進数で負の数を表す3つの方法 ― 絶対値表現・1の補数表現・2の補数表現

広告

コンピュータは数値をすべて0と1のビット列で扱います。正の数はそのまま2進数に変換すればいいですが、負の数をどう表現するかは一つに決まっているわけではなく、歴史的に複数の方式が使われてきました。本記事では代表的な3方式「絶対値表現(符号+絶対値表現)」「1の補数表現」「2の補数表現」を、8ビットの例を使って比較します。

前提:8ビットで考える

以下ではすべて8ビット(1バイト)の符号付き整数を例にします。最上位ビット(MSB)を符号ビットとして使う点は3方式に共通しています。

  • 符号ビットが 0 → 正の数
  • 符号ビットが 1 → 負の数

この後、+5 と -5 を例に、各方式でのビット表現を見ていきます。

+5 の絶対値は 2進数で 0000101 なので、8ビットにすると次のようになります。

+5 = 00000101

1. 絶対値表現(符号+絶対値表現)

最もシンプルな方式。最上位ビットを符号(0=正、1=負)とし、残りのビットに数の絶対値をそのまま入れます。

+5 = 00000101   (符号0 + 絶対値0000101)
-5 = 10000101   (符号1 + 絶対値0000101)

正の数と負の数は符号ビットが違うだけで、絶対値部分は完全に同じという分かりやすさが利点。

問題点

ゼロが2通りできます。

+0 = 00000000
-0 = 10000000

回路やソフトウェアは +0 と -0 を別物として扱わないよう特別な配慮が必要になり、比較演算が煩雑になります。

普通の2進加算がそのまま使えない。

例えば 5 + (-3) を計算したい場合、絶対値表現のビット列同士を単純に加算しても正しい答えになりません。

  00000101  (+5)
+ 10000011  (-3)
-----------
  10001000  ← これは "-8" に見えるが、正しい答えは +2

符号を見て「同符号なら絶対値を足す」「異符号なら絶対値を引いて大きい方の符号をつける」という条件分岐をハードウェアで実装する必要があり、加算器の設計が複雑になります。

表現できる範囲(8ビットの場合): -127 ~ +127(ゼロの重複がある分、1の補数表現と同じく1個少ない)

2. 1の補数表現

負の数を「対応する正の数の全ビットを反転(0と1を入れ替える)したもの」として表します。

+5 = 00000101
-5 = 11111010   (00000101 の各ビットを反転)

「反転するだけ」という単純さが利点で、絶対値表現よりは加算のハードウェアがシンプルになります。

問題点

やはりゼロが2通りできます。

+0 = 00000000
-0 = 11111111

加算に「エンドアラウンドキャリー」という補正が必要です。

  00000101  (+5)
+ 11111010  (-5)
-----------
  11111111  ← 桁上げが出ないケースはそのままだと "-0"

繰り上がり(キャリー)が最上位から出た場合、それを最下位ビットに足し戻す(エンドアラウンドキャリー)という追加処理をしないと正しい結果にならない場合があります。これも回路の複雑化につながります。

表現できる範囲(8ビットの場合): -127 ~ +127

3. 2の補数表現

現在ほぼすべてのコンピュータで採用されている方式。負の数を「1の補数表現にさらに1を足したもの」として定義します。

+5 = 00000101
     11111010   ← まず全ビット反転(1の補数)
   +        1
     ---------
-5 = 11111011   ← これが2の補数表現

もう少し実務的な求め方としては、「最下位ビットから見て、最初の1が立っているビットまではそのまま、それより上のビットをすべて反転する」というやり方もよく使われます。

利点

ゼロがただ1通りしかありません。

0 = 00000000

11111111 は「ゼロ」ではなく「-1」を表す数として使われるため、無駄なビットパターンが出ません。

普通の加算器でそのまま引き算・負の数の演算ができます。

  00000101  ( +5)
+ 11111011  ( -5)
-----------
  00000000  (  0)   ※最上位からの桁上げは単純に捨ててよい

エンドアラウンドキャリーのような補正が不要で、繰り上がりを単純に無視するだけで正しい答えになります。これはCPUの加算回路をそのまま減算にも流用できることを意味し、ハードウェアの設計が大幅に単純化されます。

  00000101  ( +5)
+ 11111101  ( -3)
-----------
1 00000010  → 桁あふれ分(最上位からの繰り上がり)は捨てる → 00000010 = +2

表現できる範囲(8ビットの場合): -128 ~ +127

正の数の個数より負の数の個数が1つ多いという非対称性がありますが、これはゼロの表現が1通りしかないことの裏返しであり、実用上ほとんど問題になります。

3方式の比較

項目絶対値表現1の補数表現2の補数表現
-5 の8ビット表現100001011111101011111011
ゼロの表現+0/-0 の2通り+0/-0 の2通り0 の1通り
8ビットでの範囲-127 ~ +127-127 ~ +127-128 ~ +127
加算・減算の回路符号判定が必要で複雑エンドアラウンドキャリーが必要そのまま加算するだけで良い
現在の実用状況ほぼ使われないほぼ使われないほぼすべてのCPUで採用

なぜ2の補数表現が主流になったのか

理由はシンプルで、加算回路だけで足し算も引き算も処理できるからです。CPUにとって回路が単純であることは、コストの低さ・速度・消費電力に直結します。ゼロの表現が1通りしかない点も、比較命令や条件分岐のロジックを単純にします。

こうした理由から、現在使われているほぼすべてのプロセッサ(x86、ARMなど)は整数の負数表現に2の補数表現を採用しています。基本情報技術者試験などでもこの3方式の違い、特に「2の補数がなぜ選ばれているか」はよく問われるポイントなので、実際にビット計算をして手を動かして確認しておくと理解が定着しやすいです。

まとめ

  • 絶対値表現:符号ビット+絶対値。直感的だが、ゼロの重複と加減算の複雑さが弱点です。
  • 1の補数表現:全ビット反転で負数を作る。絶対値表現よりは扱いやすいが、ゼロの重複とエンドアラウンドキャリーの問題が残ります。
  • 2の補数表現:1の補数に1を加えたもの。ゼロが1通りになり、加算器だけで減算も実現できるため、現代のコンピュータで標準的に採用されているます。
訪問数 2 回, 今日の訪問数 9回

広告