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

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

使い方のヒント

  • 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ビット)で発生する整数オーバーフローの挙動を理解する教材としても使えます。

よくある質問

符号絶対値表現や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では仕様上オーバーフローは静かに折り返る(ラップアラウンドする)と定められており、言語によって挙動の保証レベルが異なる点も興味深い違いです。