LASSIC Media らしくメディア

2026.07.26 らしくコラム

2の補数とは?負の数を表す仕組みの基礎

コンピュータはどうやって負の数を表すのか

プログラムコード

コンピュータの内部では、あらゆるデータが0と1の並び(ビット列)として扱われています。正の整数であれば、そのままの並びを2進数として読めば値が定まりますが、負の整数をどう表現するかは、実はそれほど単純な話ではありません。

サーバールーム

最初に思いつく方法は、ビット列の先頭1ビットを符号ビットとして「0なら正、1なら負」という取り決めをする方式(符号・絶対値表現)でしょう。ところがこの方式には、0が「+0」と「-0」の2通り存在してしまう、加算・減算の回路をそのまま使えず符号の判定を別途行う必要がある、といった扱いにくさが残ります。単に符号ビットを1本足すだけでは、実用上の課題を解決しきれないものです。

こうした課題を解決する方法として、現在ほぼすべてのコンピュータで採用されているのが「2の補数」という表現方式です。本記事は、負の整数を2進数でどのように表すかという符号付き整数の表現方法としての2の補数に焦点を当て、その仕組みとなぜこの方式が選ばれているのかを整理します。なお、小数の表現や誤差を扱う浮動小数点数、複数バイトの並び順を扱うエンディアンとは別のテーマであり、本記事ではあくまで整数の符号表現を扱う点にご留意ください。

普段アプリケーション層のコードだけを書いている場合、負の数がどうビットで表現されているかを意識する機会は多くありません。しかし、システムの土台となるCPUやOS、データベースの数値型は、内部でこの2の補数という仕組みを前提に動いています。土台の挙動を知っておくことは、桁あふれのような低レイヤ由来の不具合を設計段階で見抜くための助けになるでしょう。

2の補数とは何か

2の補数とは、あるビット数の中で正の数から対応する負の数を作り出すための計算方法です。手順は次の2ステップだけで完結します。

  • ステップ1: ビット反転(1の補数を作る): 各ビットの0と1をすべて入れ替えます。
  • ステップ2: 1を加算する: ビット反転した値に1を足します。これで2の補数(負の数の表現)が得られます。

8ビットで5を例に、具体的な変換を見てみましょう。

段階 2進数 10進数としての意味
元の値(5) 00000101 5
ビット反転(1の補数) 11111010 (そのままでは使わない中間値)
1を加算(2の補数) 11111011 -5

このように、5(00000101)をビット反転して11111010を得たのち、1を足して11111011とすることで、-5という負の数の表現が完成します。先頭ビットが1になっている点は符号・絶対値表現と似ていますが、残り7ビットの並びが絶対値そのものではない点が異なります。逆に-5から5へ戻す場合も同じ手順(ビット反転して1を足す)で計算できるため、正から負、負から正のどちらの変換も同一の操作で行える対称性を持つ仕組みです。

この手順が成り立つ背景を大まかに捉えるなら、あるビット幅で表現できる値の総数(8ビットなら256)から元の値を引いた数を求めているのと同じ計算になっている、とイメージすると理解しやすいものです。5に対する2の補数(-5の表現)は、256から5を引いた251(2進数で11111011)と一致します。ビット反転して1を足すという手順は、この「総数から引く」という計算を、桁上げの処理を含めて機械的に行うための近道だと考えられるでしょう。

なぜ2の補数が使われるのか

2の補数がコンピュータの標準的な負数表現として広く採用されているのには、主に次の3つの理由があります。

  • 加算回路をそのまま減算に使える: 「Aから Bを引く」という減算は、「Aに Bの2の補数(負の数)を足す」という加算に置き換えられます。CPUの内部に減算専用の回路を別に用意しなくても、加算回路だけで足し算・引き算の両方をこなせるため、回路設計をシンプルにできるという利点があるものです。
  • ゼロの表現が1通りに定まる: 符号・絶対値表現では+0(00000000)と-0(10000000)が別々に存在してしまいますが、2の補数では0をビット反転して1を足すと桁あふれ分が切り捨てられ、結果は00000000の1通りだけになります。「+0と-0の区別」という余計な考慮が不要になるわけです。
  • 表現できる範囲を無駄なく使える: 8ビットの2の補数表現では、-128から127までの256通りの値をすべて重複なく表せます。符号ビットを別扱いする方式に比べ、同じビット数でより広い範囲を表現できる点も実務上のメリットでしょう。

「加算回路をそのまま減算に使える」という点を、8ビットの5-3を例に確認してみましょう。5-3は5+(-3)と読み替えられ、3の2の補数は11111101(-3)なので、00000101(5)と11111101(-3)を単純に加算するだけです。結果は9ビット目への桁あふれを切り捨てて00000010、つまり2となり、5-3の答えと一致します。減算のたびに専用の回路や符号の判定処理を挟まなくても、加算した後にあふれた桁を捨てるだけで正しい結果が得られる点が、2の補数が広く使われる実務上の理由です。

ビット数と表現できる符号付き整数の範囲は、次のように整理できます。

ビット幅 符号付き整数の範囲 代表的な型名
8ビット -128 〜 127 int8 / sbyte など
16ビット -32,768 〜 32,767 int16 / short
32ビット -2,147,483,648 〜 2,147,483,647 int32 / int
64ビット 約-922京 〜 約922京 int64 / long

負側の絶対値が正側より1つ多い(8ビットなら-128〜127で負側が1つ多い)のも、2の補数特有の性質です。ゼロの表現に正の側の1通り分を割り当てる形になるため、このような非対称な範囲になります。

オーバーフローと符号の落とし穴

2の補数には利点が多い一方で、表現できるビット数には限りがあるため、その範囲を超えると値が意図しない形に「一周」してしまう現象、いわゆるオーバーフロー(桁あふれ)が起こり得ます。

たとえば8ビットの符号付き整数で上限値127(01111111)に1を足すと、ビット演算上は10000000という並びになりますが、これは2の補数表現では-128を意味します。上限値のすぐ先に下限値が来てしまうというのが、2の補数における桁あふれの典型的な挙動です。

もう1つ実務でつまずきやすいのが、符号付き整数と符号なし整数の取り違えです。同じビット列11111111でも、符号付き整数として解釈すれば-1ですが、符号なし整数として解釈すれば255になります。ビット列そのものは変わらないのに、「符号付きか符号なしか」という型の解釈だけで意味がまったく変わってしまう点は、見落とされやすい落とし穴でしょう。

下図は、8ビット符号付き整数における5から-5への変換と、上限値127に1を加算した際に下限値-128へ一周する様子を示したものです。

図

実務での関わり

2の補数の仕組みそのものは低レイヤの知識ですが、日々のシステム開発において「どのビット幅の整数型を選ぶか」「符号付きか符号なしか」という判断は、思いのほか身近な場面で発生します。

  • 整数型のビット幅の選択: 多くのプログラミング言語では、int8/int16/int32/int64(あるいはshort/int/longなど)のように扱うビット幅を選べる整数型が用意されています。想定する値の上限・下限がどの範囲に収まるかを見積もったうえで型を選ぶ必要があるでしょう。
  • 符号付き・符号なしの使い分け: 個数やインデックス、バイト長など「負の値になり得ないもの」には符号なし整数(unsigned)、差分計算や残高のように負の値も取り得るものには符号付き整数(signed)を選ぶのが基本的な考え方です。符号なし整数は、意図せず負の計算結果が発生した際に非常に大きな値へ一周してしまう(アンダーフロー)ため、差分計算には符号付きを使うほうが扱いやすい場合も少なくありません。
  • 桁あふれ対策: 集計処理やループカウンタなど、値が積み上がっていく処理では、想定より大きな型を選ぶ、あるいは言語やライブラリが提供するオーバーフロー検知機能・多倍長演算(BigIntegerなど)を利用するといった対策が取られます。

データベースの数値型を設計する際にも、同じ考え方が関わってきます。代表的なRDBMSの整数型は、次のようにビット幅と符号の有無を選べる形で提供されています。

型の例(MySQL) ビット幅 符号付きの範囲 符号なしの範囲
TINYINT 8ビット -128 〜 127 0 〜 255
SMALLINT 16ビット -32,768 〜 32,767 0 〜 65,535
INT 32ビット 約-21億 〜 約21億 0 〜 約42億
BIGINT 64ビット 約-922京 〜 約922京 0 〜 約1844京

符号なしを選べば同じビット幅でも表現できる正の値の上限をおよそ2倍に広げられますが、後から負の値を扱う要件が加わった際に型変更が必要になる点は考慮しておく必要があるでしょう。プログラミング言語側でも、Javaのようにプリミティブ型が符号付きのみで符号なし整数を直接サポートしない言語もあれば、C#やGoのようにuint/int32・uint32を明示的に使い分けられる言語もあり、選べる型の幅は言語によって異なります。またPythonの整数のように、多倍長演算(桁数に応じてメモリを自動的に広げる仕組み)によってオーバーフローそのものを気にせず扱える設計の言語も存在するものです。

桁あふれが実務で問題になりやすいのは、金額や数量の集計、IDの採番、カウンタといった、値が一定方向に増え続ける処理です。たとえば32ビット符号付き整数の上限(約21億)に近い件数までIDや連番を発行し続けるシステムでは、上限到達後に採番が負の値へ一周し、想定外の不具合につながる恐れがあります。金額の集計処理も同様で、想定より大きい取引が積み重なった際に型の上限を超えないか、設計段階で桁数の見積もりをしておくことが望ましいでしょう。再生回数や経過時間、アクセスカウンタのように値が一方向に増え続ける項目を、余裕のないビット幅でカウントする設計も、長期運用の中で桁あふれが顕在化しやすい典型例だと言えます。

発注担当者やプロジェクトマネージャーの視点では、こうした整数型の選定やオーバーフロー対策が、開発会社の設計書やレビューでどこまで検討されているかを確認しておくと、リリース後の想定外の不具合を減らす一助になります。特にデータベースのテーブル設計書に登場するINT・BIGINTといった型名の意味を押さえておくと、想定される件数や金額の桁数に見合った型が選ばれているかを、非エンジニアの立場でもある程度チェックできるようになるでしょう。

まとめ

2の補数とは、正の数のビットをすべて反転させたうえで1を加算することで、対応する負の数を導き出す表現方法です。8ビットの5(00000101)を例にとると、ビット反転で11111010、1を加算して11111011となり、これが-5を表す2進数の並びになります。

2の補数がコンピュータの標準的な負数表現として選ばれている理由は、加算回路をそのまま減算に転用できること、ゼロの表現が1通りに定まること、そして限られたビット数を無駄なく使って符号付き整数の範囲(8ビットなら-128〜127)を表現できることの3点に集約されるでしょう。

一方で、表現できる範囲を超えると値が一周してしまうオーバーフローや、符号付き・符号なしの解釈違いによる値のずれは、実務で不具合として現れやすいポイントです。整数型のビット幅や符号の有無を設計段階で適切に見積もり、桁あふれが起こり得る箇所を洗い出しておくことが、安定したシステム設計につながります。

相談するメリット

整数のオーバーフローや符号付き/符号なしの取り違えは、通常のテストケースでは見逃されがちで、想定より大きな取引量やデータ件数が積み上がった本番環境で初めて表面化することが少なくありません。特に金額計算やID採番、大量データの集計処理を扱うシステムでは、設計時点で整数型のビット幅や桁あふれのリスクを点検しておくことが重要です。LASSICでは、ニアショア開発体制を生かした受託開発の中で、既存システムの整数型・オーバーフロー観点でのコードレビューや、堅牢なデータ設計の支援に対応しています。桁あふれのリスクや型設計に不安がある場合は、お気軽にご相談ください。

よくある質問

なぜ1の補数ではなく2の補数が使われるのですか。

1の補数(ビット反転のみ)では、2の補数と同様に+0と-0が別々に存在してしまい、ゼロの判定や演算処理が複雑になります。2の補数はビット反転に1を加算する一手間を加えることで、ゼロの表現を1通りにまとめ、加算回路だけで減算も行えるようにしている点が大きな違いです。

符号付き整数と符号なし整数はどう選べばよいですか。

個数やインデックス、バイト長のように負の値を取らないものは符号なし整数、差分や残高のように負の値も発生し得るものは符号付き整数を選ぶのが基本的な考え方です。符号なし整数は、計算結果が負になった際に非常に大きな値へ一周してしまうため、減算を伴う処理では符号付きを使うほうが扱いやすい場合もあります。

8ビットより大きい16/32/64ビットの整数でも仕組みは同じですか。

はい、ビット反転して1を加算するという2の補数の手順自体はビット幅が変わっても同じです。異なるのは表現できる範囲で、ビット数が増えるほど-2^(n-1)から2^(n-1)-1までの範囲が広がっていきます。

オーバーフローが起きるとプログラムはどうなりますか。

言語や実行環境によって挙動は異なるものです。C言語のような言語では、符号付き整数のオーバーフローは未定義の動作とされ、値が一周する、あるいは想定外の結果になることがあります。一方でPythonの整数のように多倍長演算に対応した言語・型では、桁あふれを気にせず大きな値を扱える設計になっています。

著者:テレリモ総研編集部 鈴木 亮佑

整数型の設計や既存システムの桁あふれリスクの点検でお困りの際は、ニアショア開発によるコスト最適化と品質確保を両立するLASSICにご相談ください。要件のヒアリングから設計、実装まで伴走いたします。

出典


View