数値の進数変換とは、同じ数値を異なる位置記数法で表現するプロセスです。すべての整数は一つの真の値を持ち、進数はその値の表記方法を決めるだけです。10進数の255、16進数の0xFF、2進数の0b11111111、8進数の0377はすべて同一の量を4つの記法で表したものです。
数値の進数(基数)とは
数値の進数(基数)は、システムが「桁上がり」する前に使用できる固有の数字の数を定義します。桁の値は右から左へ進数の累乗になります。
2進数(基数2)
0 と 1 のみを使います。桁の値は2の累乗:1、2、4、8、16、32、64、128、…
2進数はデジタルハードウェアのネイティブ言語です。すべての論理演算、メモリセル、CPU命令は最終的にビットのシーケンスに帰着します。ビット演算、ネットワークマスク、ハードウェアレジスタを扱うときに2進数を直接目にします。
8進数(基数8)
0〜7 の数字を使います。桁の値は8の累乗:1、8、64、512、…
8進数は2進数のコンパクトな省略形で、1桁の8進数はちょうど3ビットを表します。一般的な用途では廃れましたが、Unixファイルのパーミッションマスクには今でも非常に関連性があります — chmod 755 や chmod 644 は8進数の値です。
10進数(基数10)
0〜9 の数字を使います。人間がデフォルトで使うシステムです。ほとんどのプログラミング言語は、プレフィックスがない限り数値リテラルを10進数として解析します。
16進数(基数16)
0〜9 と A〜F の文字を使います。1桁の16進数はちょうど4ビットを表し、2進数データの最もコンパクトな人間が読めるエンコーディングです。
16進数はソフトウェア全体で使われています:CSSカラー(#FF5733)、メモリアドレス(0x7ffee4b2c8a0)、SHAハッシュ、MACアドレス、UUIDフィールド、バイナリファイルの検査すべてで16進数表記が使われます。
進数間の変換方法
手動計算
10進数から他の進数へ — 繰り返し除算:
10進数42を2進数に変換するには:
42 ÷ 2 = 21 余り 0
21 ÷ 2 = 10 余り 1
10 ÷ 2 = 5 余り 0
5 ÷ 2 = 2 余り 1
2 ÷ 2 = 1 余り 0
1 ÷ 2 = 0 余り 1
余りを下から上へ読む:101010。よって10進数42 = 2進数101010。
他の進数から10進数へ — 位置展開:
16進数2Aを10進数に変換するには:
2A = (2 × 16¹) + (10 × 16⁰)
= 32 + 10
= 42
JavaScriptで
JavaScriptのparseIntとtoStringは進数変換をネイティブに処理します:
// 10進数から他の進数へ
const n = 255;
console.log(n.toString(2)); // "11111111" (2進数)
console.log(n.toString(8)); // "377" (8進数)
console.log(n.toString(16)); // "ff" (16進数)
// 任意の進数から10進数へ
console.log(parseInt("11111111", 2)); // 255
console.log(parseInt("377", 8)); // 255
console.log(parseInt("ff", 16)); // 255
// 進数から進数(10進数を経由)
function convertBase(value, fromBase, toBase) {
return parseInt(value, fromBase).toString(toBase);
}
console.log(convertBase("ff", 16, 2)); // "11111111"
console.log(convertBase("377", 8, 16)); // "ff"
Pythonで
Pythonは組み込み関数とプレフィックスリテラルを提供します:
# 10進数から他の進数へ
n = 255
print(bin(n)) # '0b11111111'
print(oct(n)) # '0o377'
print(hex(n)) # '0xff'
# 必要ならプレフィックスを取り除く
print(format(n, 'b')) # '11111111'
print(format(n, 'o')) # '377'
print(format(n, 'x')) # 'ff'
print(format(n, 'X')) # 'FF' (大文字)
# 任意の進数から10進数へ
print(int('11111111', 2)) # 255
print(int('377', 8)) # 255
print(int('ff', 16)) # 255
# 直接プレフィックスリテラル
print(0b11111111) # 255
print(0o377) # 255
print(0xFF) # 255
プログラミングでの各進数の使いどころ
2進数 — ビット演算とフラグ
2進数はビットレベルで作業するときに自然な選択です:
// ビットマスクを使ったパーミッションフラグ
const READ = 0b100; // 4
const WRITE = 0b010; // 2
const EXECUTE = 0b001; // 1
const userPerms = READ | WRITE; // 0b110 = 6
const canRead = userPerms & READ; // パーミッション設定時にtrue
const canExec = userPerms & EXECUTE; // 0 — 実行権限なし
ネットワークプログラミングはサブネット計算に2進数マスクを使います。ハードウェアドライバはレジスタの個別制御ビットを設定するのに2進数を使います。
8進数 — Unixファイルパーミッション
chmod コマンドは8進数の引数を取ります。3桁の8進数でオーナー/グループ/その他のパーミッションをエンコードし、各桁は r=4、w=2、x=1 です:
chmod 755 script.sh # rwxr-xr-x
chmod 644 config.txt # rw-r--r--
chmod 600 id_rsa # rw------- (秘密鍵)
Pythonでは、os.open と os.chmod に渡すファイルモードは8進数リテラルである必要があります:
import os
os.chmod('script.sh', 0o755)
16進数 — カラー、アドレス、バイナリデータ
CSSとデザイン: RGBカラーは3つの16進バイトペアに直接マッピングされます。
/* #RRGGBB */
color: #FF5733; /* R=255, G=87, B=51 */
color: #1a1a2e; /* ダークネイビー */
メモリとポインタ: デバッガとクラッシュダンプは16進数でアドレスを表示します。4ビットニブルと8ビットバイトにきれいに対応するからです。
ハッシュとエンコーディング: SHA-256出力、gitコミットハッシュ、UUID、APIキーは慣例的に16進数エンコードされたバイナリデータです。
import hashlib
h = hashlib.sha256(b"hello").hexdigest()
print(h) # 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
ネットワークプロトコル: Ethernetフレーム、IPヘッダー、TLSレコードはすべてWiresharkなどのツールで16進数で検査されます。
オンラインで数値を変換
コードを書かずにすばやく変換するには、ZeroToolの数値進数コンバーターでブラウザ内で任意の整数を2進数・8進数・10進数・16進数で即座に変換できます。任意のフィールドに値を貼り付けると、他のすべての進数がリアルタイムで更新されます — サーバーリクエストなし、データ送信なし。
役立つ場面:
- 16進数カラー値を10進数RGBにデコード
- chmodの8進数値を確認してパーミッションを検証
- ビット演算ロジックのために2進数表現を探索
- フォーマット間でメモリアドレスを変換