記事一覧へ戻る
読了 約 5

進数変換とビット演算 - 「なぜ16進数なのか」を実務目線で理解する

#development

執筆: デジタル道具屋 編集部 / 低レイヤー担当

ファームウェア開発、組込み、画像処理など、ビット単位での扱いが日常になる領域での経験を持つ編集チームです。

本記事の執筆方針と編集ポリシーについてはAbout ページをご覧ください。

導入:「16進数を読まないといけない場面」は意外に多い

男の子
男の子
「博士〜! デバッグ中に 0xDEADBEEF っていう値を見つけたんだぜ。これって何かのジョークかよ?」
博士
博士
「ふむ、それは『DEAD BEEF』と読める語呂合わせの値で、メモリの初期化や未使用領域マーカーとして使われる伝統的な値じゃよ。16進数を読めると、デバッグの効率が段違いになるのじゃ。」
女の子
女の子
「カラーコード #FF0000 も 16進数だし、Unicode の文字コードも 16進数。Web 開発でも『読めると便利』を超えて『読めないと詰む』場面が結構あるわ。」

1. なぜ「16進数」なのか

博士
博士
「コンピュータは 2進数で動いておるが、人間が 2進数を直に読むのは大変じゃ。11111111FF、どちらが速く認識できるかね?」
16進数が好まれる理由
  • 4ビット = 1桁:1バイト(8ビット)が 2桁できれいに表現できる
  • 視認性:32 ビット値が 8桁、64 ビット値が 16桁。一目でビット幅がわかる
  • 歴史的経緯:CPU レジスタの幅、メモリアドレス、文字コード表など、低レイヤの世界では事実上の標準

ちなみに 8進数(octal)は、Unix のファイルパーミッション 0755chmod 644 で今も現役です。 3ビット = 1桁の対応で、rwx の3ビットを表現するのに都合が良かったため残っています。

2. ビット演算で書ける「権限フラグ」

男の子
男の子
「権限管理ってデータベースに can_read, can_write, can_delete って列を作るんじゃないのかよ?」
博士
博士
「列を増やす方法もあるが、フラグが10個20個と増えるなら、整数1つにビットで詰める方法が圧倒的にシンプルじゃ。」
const READ    = 0b0001; //  1
const WRITE   = 0b0010; //  2
const DELETE  = 0b0100; //  4
const ADMIN   = 0b1000; //  8

// 「読み書き可能、削除不可、管理者でない」
const perm = READ | WRITE; // → 3 (0b0011)

// 権限チェック
const canDelete = (perm & DELETE) !== 0; // → false
const canWrite  = (perm & WRITE) !== 0;  // → true

// 削除権限を付与
const newPerm = perm | DELETE; // → 7 (0b0111)

// 削除権限を剥奪
const restored = newPerm & ~DELETE; // → 3
女の子
女の子
「DBには整数1列で済むし、`AND` 1回で権限チェックできるから速いの。Linux のファイルパーミッションも同じ仕組みよ。」

注意:JavaScript のビット演算は 32bit まで

JavaScript のビット演算子は符号付き 32bit 整数に変換して動作します。 32 ビット目(最上位)に立ったビットは負数として扱われ、思わぬ結果になります。 Bigger なフラグセットを扱う場合は BigInt を使うか、複数の整数に分割しましょう。

3. 文字コードを読み解く

絵文字や漢字が文字化けして「?」になったとき、原因究明には Unicode コードポイントを 16進数で読む力が要ります。

'あ'.codePointAt(0).toString(16)
// → "3042" (Unicode U+3042)

'😀'.codePointAt(0).toString(16)
// → "1f600" (Unicode U+1F600)

// UTF-8 では何バイト?
new TextEncoder().encode('あ').length    // → 3
new TextEncoder().encode('😀').length    // → 4
博士
博士
「『絵文字を文字数カウントしたら 2 になった』『DB の VARCHAR に絵文字が入らない』といった事故は、サロゲートペア(UTF-16 の上位 0xD800-0xDBFF と下位 0xDC00-0xDFFF の組)を 1文字として扱えていないのが原因じゃ。」

4. 進数変換が日常で必要になるシーン

実務シーン例
  • カラーコード:HEX #FF6347 を RGB (255, 99, 71)
  • 権限・ステータスフラグ:DB に保存された整数からビットを読み取る
  • ネットワーク:IPv4 サブネットマスク、IPv6 アドレス
  • セキュリティ:ハッシュ値、JWT のヘッダ・ペイロードを Base64URL でデコード
  • 組込み・低レイヤ:レジスタ値の読解、メモリダンプ

5. 実際に変換してみる

即座に進数を変換するなら、進数変換ツールが便利です。 2進・10進・16進・8進の相互変換に加え、入力した数のビットパターンも視覚的に確認できます。

関連: カラーコード変換(HEX↔RGB)、ハッシュ生成(生成結果は通常 16進数文字列)。

🚨 現場の失敗あるある

JavaScript で parseInt('08') がブラウザによって 0 を返した時代がありました。 第2引数(基数)を必ず明示する parseInt('08', 10) の習慣を付けると、 旧仕様への後方互換が原因のバグを未然に防げます。

参考にした一次情報

本記事の内容は、以下の公式仕様や一次情報を参照して執筆しています。