16進数の補数(2の補数)の求め方 - 負の数の表現方法Two's complement in hexadecimal: representing negative numbers
0xFB が、8bitの符号付き整数ではなぜ -5 になるのでしょうか。16進数の負の数や マイナス値は、固定したビット幅の中で2の補数として表すのが一般的です。この記事では 「16進数 補数」の意味から、補数計算・補数変換、符号ありの16進数を読む方法まで、8bitの具体例で整理します。
Negative hexadecimal values are normally encoded in a fixed-width bit pattern using two's complement. This guide explains why computers use it, how to calculate it, and how to interpret the sign bit with an 8-bit example.
TL;DR
- 負数は、固定長のビット列だけで符号と値を同時に扱える2の補数で表す
- 1の補数は全ビット反転、2の補数は全ビット反転してから1を足す
- 8bitでは
-5 = 0xFB。16bitなら0xFFFB、32bitなら0xFFFFFFFB - 最上位ビットが0なら非負、1なら負。ビット幅なしでは符号付きの値は確定しない
1. なぜマイナス記号ではなく補数を使うのか / Why complement notation is used
人が書く数値なら -5 のようにマイナス記号を追加できます。しかしCPUのレジスタやメモリに保存される整数は、 8bit、16bit、32bitなど長さが固定された0と1の列です。マイナス記号専用の文字を別に置かず、 決められたビット列の中に符号と数値を一緒に収める必要があります。
2の補数なら同じ加算回路で正数と負数を計算でき、最上位からあふれた桁を捨てるだけで減算も実現できます。 8bitでは 5 + 0xFB = 0x100 となり、9bit目を捨てると 0x00、つまり5 + (-5) = 0 です。これがコンピュータアーキテクチャで補数を使う理由です。
2. 1の補数と2の補数の違い / One's vs two's complement
| 方式 | 求め方 | 8bitで-5 | 特徴 |
|---|---|---|---|
| 1の補数 | 全ビットを反転 | 0xFA | +0と-0が存在する |
| 2の補数 | 全ビットを反転して+1 | 0xFB | 0が1種類で加減算を共通化できる |
両者は名前が似ていますが、最後の +1 の有無が重要です。現代のCPUやプログラミング言語で 実務上使われる符号付き整数表現は、ほぼ2の補数です。
3. 8bitの-5を16進数へ変換する手順 / Converting -5 to 8-bit hex
16進数の補数計算は、同じビット幅の2進数として考えると明確です。
00000101 = 0x0511111010 = 0xFA11111011 = 0xFB 00000101 = 0x05 (+5)
→ 11111010 = 0xFA (ビット反転: 1の補数)
+ 00000001
------------
11111011 = 0xFB (2の補数、つまり-5)よって8bit符号付き整数の -5 は 0xFB です。16bitや32bitでも手順は同じで桁数だけが変わり、 16bitでは 0xFFFB、32bitでは 0xFFFFFFFB になります。
4. 符号ビットと8bitの値の範囲 / Sign bit and 8-bit ranges
2の補数では最上位の符号ビットが0なら非負、1なら負です。同じビット列でも符号あり・なしで値が変わります。
| 最上位ビット | 16進数の範囲 | 8bit符号付きの値 |
|---|---|---|
| 0 | 0x00〜0x7F | 0〜127 |
| 1 | 0x80〜0xFF | -128〜-1 |
0xFF は符号なし8bitなら255、符号付き8bitなら-1です。「16進数 負の値」を判断するときは、ビット幅と符号ありか符号なしかを確認してください。16進数自体ではなく、解釈する型が意味を決めます。
5. JavaScriptで2の補数を確認する / Verify with JavaScript
JavaScriptのビット演算は内部で32bit符号付き整数を使うため、8bitの結果は & 0xFF で取り出します。
const value = 5;
// 全ビット反転して1を足し、下位8bitだけを残す
const twosComplement = (~value + 1) & 0xFF;
twosComplement.toString(16).toUpperCase(); // "FB"
// 2^8から値を引く別解法
const anotherWay = (0x100 - value) & 0xFF;
anotherWay.toString(16).toUpperCase(); // "FB"
// 8bitの符号付き整数として読み戻す
const hex = 0xFB;
const signed = hex & 0x80 ? hex - 0x100 : hex;
console.log(signed); // -5一般にN bitの負数 -x のパターンは 2^N - x です。マスクも8bitなら0xFF、16bitなら 0xFFFF のように幅を合わせます。
6. よくある間違い / Common mistakes
- ビット幅を決めない: -1は8bitなら
0xFF、16bitなら0xFFFFです。 - 1の補数で止める: 反転後に1を足して初めて2の補数になります。
- 先頭桁だけで負と決める:
0xFFが負なのは8bit符号付きとして読む場合です。 - JavaScriptでマスクを忘れる: 8bit表現には
& 0xFFが必要です。
English summary
Two's complement stores a negative number inside a fixed-width bit pattern, allowing hardware to use ordinary binary addition for positive and negative values. To encode -5 in 8 bits, start with 0x05, invert every bit to get 0xFA, then add one to get 0xFB. The sign bit is 0 for non-negative values and 1 for negative values. The procedure is unchanged for 16-bit and 32-bit integers; only the width changes.
まとめ / Summary
16進数のマイナス計算では、まずビット幅と符号付きを確定します。2の補数は「全ビット反転して1を足す」、 または「2のビット幅乗から絶対値を引く」ことで求めます。8bitの-5は 0x05 → 0xFA → 0xFB です。 結果は Hex Converterで実際に試せます。