2の補数計算ツール(符号付き整数の2進数変換)

符号付き10進数を8/16/32/64ビットの2の補数ビットパターンに変換、またはその逆を変換します。符号なし整数としての解釈・16進数表記・範囲外エラーの検出にも対応。

2の補数(Two's Complement)とは

2の補数とは、コンピューターが負の数を含む符号付き整数をビット列で表現するための方式です。正の数はそのまま2進数にし、負の数は「絶対値のビットをすべて反転させて1を足す」ことで作られます。最上位ビット(MSB)が1なら負数、0なら正数と解釈するのが特徴で、8/16/32/64ビットといったビット幅ごとに表現できる範囲が定まります。

このツールでは符号付き10進数を指定したビット幅の2進数(2の補数表現)に変換し、逆に2進数から10進数へ変換することもできます。あわせて符号なし整数として解釈した場合の値・16進数表記・符号絶対値表現との比較も表示するため、ビットパターンがどのように解釈され分かれるのかを具体的な数値で確認できます。

2の補数計算ツールの使い方

  1. ビット幅を選ぶ 8・16・32・64ビットから、確認したい整数型のビット幅を選択します。
  2. 変換の向きを選ぶ 「10進数→2進数」か「2進数→10進数」のどちらに変換したいかを切り替えます。
  3. 値を入力する 符号付き10進数(例: -5)、または2進数のビット列(例: 11111011)を入力します。
  4. 変換結果を確認する 符号付き/符号なしの10進数、2の補数のビットパターン、16進数表記が同時に表示されます。
  5. 範囲外エラーを確認する ビット幅で表現できる範囲を超える値を入力するとエラーになり、オーバーフローの境界を確認できます。

使いこなすためのヒント

  • 8ビットの符号付き整数の範囲は -128〜127 です。127に1を足すと-128に「オーバーフロー」して折り返る様子を、実際に127→128を入力して確認できます(128はエラーになりますが、これがまさにオーバーフローの境界です)。
  • 「符号なし10進数」の行は、同じビット列を符号ビットのないただの整数として読んだ場合の値です。負の値をこの行と見比べると、符号付き/符号なしの解釈の違いが一目でわかります。
  • 2進数の入力は必ず選択したビット幅と同じ桁数にする必要があります。8ビットなら8桁、16ビットなら16桁ちょうどで入力してください。
  • 64ビットの計算はJavaScriptのNumber型では精度が失われるため、内部的にBigIntを使用しています。2^63に近い大きな値でも誤差なく変換できます。
  • C言語やJavaのint型(32ビット)・long型(64ビット)で発生する整数オーバーフローの挙動を理解する教材としても使えます。

2の補数計算の活用シーン

情報系の授業・試験対策

大学や専門学校の情報系科目で必ず出てくる2進数変換の課題を、実際に手を動かしながら検算できます。

C言語や組み込み開発の整数オーバーフロー調査

int型やuint8_t型で発生した予期しない値を、実際のビット幅で再現して原因を特定するのに役立ちます。

CPUレジスタの内部表現の理解

デバッガでレジスタの16進数値を見たとき、それが符号付きでいくつを意味するのかをすぐ確認できます。

ビット演算結果の検証

AND・OR・シフト演算などのコードを書く前後で、想定通りのビットパターンになっているかを手元で照合できます。

2の補数に関する用語集

2の補数(Two's Complement)
負の数を、絶対値のビットをすべて反転させて1を足すことで表す方式です。ゼロの表現が1通りに定まり、加算回路をそのまま減算にも使えるため現代のほぼ全CPUが採用しています。
符号ビット(Sign Bit)
ビット列の最上位ビット(MSB)のことで、2の補数表現ではこれが1なら負数、0なら正数を表します。
オーバーフロー(Overflow)
計算結果がそのビット幅で表現できる範囲を超えてしまう現象です。上位ビットが切り捨てられ、符号ビットの意味が変わることで値が反対側に折り返って見えます。
符号付き整数・符号なし整数(Signed / Unsigned Integer)
同じビット列でも、符号ビットを負数の印として扱うか(符号付き)、すべてのビットを数値として扱うか(符号なし)で解釈される値が変わります。
ビット幅(Bit Width)
整数を表現するために使うビットの本数です。8/16/32/64ビットが代表的で、幅が大きいほど表現できる数値の範囲が広がります。
1の補数(One's Complement)
正の数のビットをすべて反転させるだけで負数を作る古い方式です。「+0」と「-0」の2通りのゼロが生じる欠点があり、これを解消するために2の補数が広く使われるようになりました。

よくある質問

符号絶対値表現や1の補数表現では「+0」と「-0」という2通りのゼロが生まれてしまい、比較や演算の回路が複雑になります。2の補数表現ではゼロのビットパターンが1通りに定まる上、加算回路をそのまま減算にも流用できるため、CPUの演算装置(ALU)を単純化できます。この2つの利点から、現代のほぼすべてのCPUが符号付き整数の内部表現として2の補数を採用しています。

-128〜127です。最上位ビットが符号を表すため、正の数として表現できる範囲は0〜127(7ビット分)ですが、負の数は-1〜-128の128通りを表現でき、正負で非対称な範囲になります。これは2の補数のゼロが1通りしかなく、その分を負数側の表現力に回せるためです。

1の補数は正の数のビットをすべて反転させるだけで負数を作りますが、2の補数はさらにそこへ1を足します。1の補数には「+0(00000000)」と「-0(11111111)」という2通りのゼロが存在してしまう欠点があり、これを解消するために1を足す2の補数表現が広く採用されるようになりました。

ビット幅が固定されているため、表現できる範囲を超える計算結果は上位ビットが切り捨てられ、符号ビットの意味が変わってしまうからです。例えば8ビット符号付き整数で最大値127に1を足すと、ビット演算上は10000000となり、これは符号付きの解釈では-128を意味します。範囲の上限を超えると下限側に折り返る、という直感に反する動作がオーバーフローの正体です。

ビット列そのものは変わりませんが、最上位ビットを符号として扱わずすべて数値として読むため、同じビットパターンでも値が変わります。例えば8ビットの11111011は、符号付きなら-5ですが、符号なしなら251になります。C言語のunsigned intのように「符号を持たない」型を使う場面で、このビットパターンの再解釈が実際に発生します。
ツールくん

余談ですが ― なぜコンピューターは2の補数を使うのか

負の数をビット列で表す方法は2の補数だけではありません。最上位ビットを符号として扱う「符号絶対値表現」や、正の数のビットをすべて反転させるだけの「1の補数表現」も歴史的に使われてきました。しかしこの2つには共通の欠点があります。0を表すビットパターンが「+0」と「-0」の2通り存在してしまい、比較演算や回路設計が複雑になるのです。2の補数表現ではこの「2つのゼロ問題」が起こらず、ビットパターンとゼロは1対1に対応します。

さらに2の補数の最大の利点は、足し算の回路がそのまま引き算にも使えることです。CPUは正の数か負の数かを意識せず、単純にビット列同士を加算するだけで正しい結果が得られます(減算は「補数を足す」ことで実現できるため)。専用の減算回路や符号判定ロジックを追加で持つ必要がなく、演算装置(ALU)を単純化できるため、ほぼすべての現代のCPUアーキテクチャが符号付き整数の表現方式として2の補数を採用しています。

オーバーフローという現象も2の補数表現の直接的な帰結です。8ビット符号付き整数で127(01111111)に1を足すと、ビット演算上は単純に1繰り上がって10000000、つまり-128になります。C言語では符号付き整数のオーバーフローは「未定義動作」とされ、コンパイラの最適化によって予期しない挙動を招くことがあるため、実務でもこの境界値の扱いには注意が必要です。一方Javaでは仕様上オーバーフローは静かに折り返る(ラップアラウンドする)と定められており、言語によって挙動の保証レベルが異なる点も興味深い違いです。