Skip to content
ブログに戻る
チュートリアル

基数変換ガイド:2進数・16進数・8進数・10進数の相互変換と実践

2進数・16進数・8進数・10進数の変換方法をステップごとに解説。JS/Python/Go/Cのコード例と実務ユースケース付き。無料オンラインツールですぐに実践。

14分で読了

基数変換ガイド:2進数・16進数・8進数・10進数の相互変換と実践

ある午後、デバッガで 0x7FFF5FBFF8C0 を眺め、CSSファイルで #FF5733 を調整し、ターミナルで chmod 755 を叩く。3つの異なる数値表現だが、根底にあるのは同じ算術だ。16進数と2進数の変換で手が止まったり、Unixのパーミッションがなぜ8進数なのか疑問に思ったりしたことがあるなら、この記事でそれらの繋がりが明確になるはずだ。

プログラミングで日常的に使う4つの基数、覚えておくべき3つの変換方法、そしてJavaScript・Python・Go・Cの実コードを順に解説する。理論を飛ばして数値を変換したいだけなら、基数変換ツールを開こう。2から36までの任意の基数に対応し、精度に制限はない。

開発者が使う4つの基数

各基数がプログラミングに存在するのは実用的な理由による。

2進数(Base 2)——マシンの言語

使う数字は 01 の2つ。トランジスタはオンかオフか——この物理的制約が2進数を生んだ。ビットマスク、フラグ管理、ビット演算、IPサブネット計算で直接扱うことになる。

2進数はすぐに長くなる。10進数の255は2進数で 11111111——3桁の値に8桁が必要だ。個々のビット位置に意味がある場面以外、生の2進数を書く場面は少ない。

8進数(Base 8)——Unixの略記法

使う数字は 0 から 7 の8つ。各8進数字はちょうど3ビットに対応する。Unixファイルパーミッションが8進数を使うのはそのためだ。chmod 755 は3つの3ビットグループを3桁の読みやすい数字に圧縮している。

PDP-11の時代にはもっと広く使われていたが、今はほぼUnixパーミッション専用だ。Cの 0 プレフィックスリテラル(0177 を10進数の177だと思って書くバグの原因)で見かけることもある。

10進数(Base 10)——人間のデフォルト

使う数字は 0 から 9 の10個。脳が自然に使う基数であり、ポート番号、配列インデックス、HTTPステータスコード、ピクセル寸法はすべて10進数だ。コンピュータ内部は10進数で動いていないが、人間がそうなので、ユーザー向けの数値はすべてBase 10で出力される。

16進数(Base 16)——開発者のスイスアーミーナイフ

16個のシンボル:0-9A-F。各16進数字はちょうど4ビット(1ニブル)を表す。16進2桁 = 1バイト。常にそうだ。

メモリアドレス(0x7FFF5FBFF8C0)、CSSカラー(#FF5733)、MACアドレス(00:1A:2B:3C:4D:5E)、UUIDフォーマット、ハッシュダイジェストで16進数に出会う。バイトレベルプログラミングの共通言語だ。

基数変換ツールで4つの基数間の変換を試そう。任意の基数で値を入力すれば、残りがリアルタイムで更新される。

基数変換の仕組み:3つの基本手法

ツールなしでも変換はできる。3つの手法ですべてのケースをカバーする。

手法1——位取り展開(任意の基数 → 10進数)

位取り記数法はすべて同じ仕組みだ。各桁の数字に「基数のその桁乗」を掛けて合計する。右端が0乗。

2進数 1011

1×2³ + 0×2² + 1×2¹ + 1×2⁰
= 8   + 0    + 2    + 1
= 11

16進数 FF

15×16¹ + 15×16⁰
= 240   + 15
= 255

コードでは、ほとんどの言語に解析関数がある:

parseInt('1011', 2)   // 11
parseInt('FF', 16)    // 255
parseInt('755', 8)    // 493

手法2——連続除算(10進数 → 任意の基数)

逆方向の変換は、10進数を目標基数で繰り返し割り、余りを集めて下から上に読む。

10進数 255 → 16進数:

255 ÷ 16 = 15  余り 15 (F)
 15 ÷ 16 =  0  余り 15 (F)
→ 下から読む:FF

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
bin(42)    # '0b101010'
hex(255)   # '0xff'
oct(493)   # '0o755'

手法3——ビットグルーピング(2進数 ↔ 16進数/8進数の直接変換)

経験豊富な開発者が最も頻繁に使う方法だ。16 = 2⁴、8 = 2³ なので、2進数と16進数(または8進数)の間はビットをグループ化するだけで変換できる。計算不要。

2進数 → 16進数: 右から4ビットずつ(ニブル)にグループ化。左端が足りなければゼロで埋める。

2進数:  1010 1111
16進数:  A    F
→ AF

2進数 → 8進数: 右から3ビットずつにグループ化。

2進数:111 101 101
8進数: 7   5   5
→ 755

ニブル対応表は暗記する価値がある:

2進数16進数2進数16進数
0000010008
0001110019
001021010A
001131011B
010041100C
010151101D
011061110E
011171111F

この表を覚えれば、2進数から16進数への変換は一瞬だ。

各言語での基数変換コード

基数変換が頻繁に登場する4言語の実用コード。

JavaScript / TypeScript

// 解析:任意基数の文字列 → 数値
parseInt('FF', 16)          // 255
parseInt('101010', 2)       // 42
parseInt('755', 8)          // 493

// フォーマット:数値 → 任意基数の文字列
(255).toString(16)          // 'ff'
(42).toString(2)            // '101010'
(493).toString(8)           // '755'

// リテラル
const bin = 0b11111111;     // 255
const oct = 0o377;          // 255
const hex = 0xff;           // 255

// BigInt:2⁵³を超える値に対応
const big = BigInt('0xFFFFFFFFFFFFFFFF');
big.toString(2)             // 64個の1
big.toString(10)            // '18446744073709551615'

Python

# 10進数 → 他の基数(プレフィックス付き文字列)
bin(255)          # '0b11111111'
oct(493)          # '0o755'
hex(255)          # '0xff'

# 他の基数 → 10進数
int('11111111', 2)    # 255
int('FF', 16)         # 255
int('755', 8)         # 493

# パディング付きフォーマット出力
f'{255:08b}'      # '11111111'(8桁2進数、ゼロ埋め)
f'{255:02x}'      # 'ff'(16進数、小文字)
f'{255:02X}'      # 'FF'(16進数、大文字)

# Pythonの整数は標準で任意精度
big = int('F' * 64, 16)   # 256ビットの数値、オーバーフローなし

Go

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // フォーマット:int → 任意基数の文字列
    fmt.Println(strconv.FormatInt(255, 16))  // "ff"
    fmt.Println(strconv.FormatInt(255, 2))   // "11111111"
    fmt.Println(strconv.FormatInt(493, 8))   // "755"

    // 解析:任意基数の文字列 → int
    n, _ := strconv.ParseInt("FF", 16, 64)  // 255
    fmt.Println(n)

    // Printf動詞
    fmt.Printf("%b %o %x %d\n", 255, 255, 255, 255)
    // 11111111 377 ff 255
}

C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main() {
    // 10進数、8進数、16進数で出力
    printf("%d %o %x\n", 255, 255, 255);
    // 255 377 ff

    // 任意基数から解析
    long val = strtol("FF", NULL, 16);   // 255
    long bin = strtol("101010", NULL, 2); // 42

    // Cには2進数出力のprintf書式がない——手動でビット抽出:
    uint8_t byte = 0xAF;
    for (int i = 7; i >= 0; i--)
        putchar(((byte >> i) & 1) ? '1' : '0');
    // 10101111

    return 0;
}

実務での基数変換シナリオ

基数変換が教科書の知識ではなく実務になる5つの場面。

1. メモリアドレスのデバッグ

デバッガがポインタを 0x7FFF5FBFF8C0 と表示している。末尾2バイトを2進数に変換すると 1000 1100 0000 ——末尾に6個のゼロがあり、64バイト境界にアラインされていることがわかる。アラインメントはキャッシュ性能、SIMD演算、メモリマップドI/Oに影響する。

ポインタ演算も16進数の方が把握しやすい。ベースアドレスから 0x100 オフセットは正確に256バイト——多くの組み込みシステムで1ページ分だ。

2. CSS 16進カラー ↔ RGB

#FF5733 は3バイトの16進ペア:

ペア16進数10進数チャネル
FFFF255赤(最大値)
575787
333351

省略記法の #F00#FF0000(純粋な赤)に展開される。8桁表記の #FF573380 はアルファチャネルを追加し、80(10進数128)は約50%の不透明度を意味する。

3. Unixファイルパーミッション(8進数)

chmod 755 の内訳:

7 → 111 → rwx(所有者:読み取り+書き込み+実行)
5 → 101 → r-x(グループ:読み取り+実行)
5 → 101 → r-x(その他:読み取り+実行)

各8進数字がパーミッショングループ1つをエンコードする。3つのパーミッションビット(読み取り=4、書き込み=2、実行=1)が1つの8進数字(0-7)に対応するからだ。よく使う組み合わせ:

8進数2進数パーミッション典型的な用途
755111 101 101rwxr-xr-x実行ファイル、ディレクトリ
644110 100 100rw-r--r--通常のファイル
700111 000 000rwx------プライベートスクリプト
600110 000 000rw-------SSH鍵、秘密情報

4. ネットワークサブネット計算

/24 サブネットマスクは2進数で先頭24個が1:

11111111.11111111.11111111.00000000
→ 255.255.255.0

ネットワークアドレスを求めるには、IPとマスクをビットANDする:

192.168.1.37   → 11000000.10101000.00000001.00100101
255.255.255.0  → 11111111.11111111.11111111.00000000
AND結果        → 11000000.10101000.00000001.00000000
               → 192.168.1.0(ネットワークアドレス)

ネットワークエンジニアは10進数(IP表記)、2進数(サブネット計算)、16進数(パケットキャプチャ)を日常的に行き来する。基数変換ツールで各オクテットを個別に検証できる。

5. ハッシュダイジェストとUUIDの読み方

MD5ハッシュ d41d8cd98f00b204e9800998ecf8427e は16進数32文字 = 16バイト(128ビット)。16進2桁が1バイトに対応する。

UUIDは 8-4-4-4-12 の16進数フォーマット:

550e8400-e29b-41d4-a716-446655440000

ハイフン区切りの16進32桁——同じ128ビットの別のフォーマットだ。13番目のニブル(41d44)がUUID v4を示す。

MD5 & SHAハッシュジェネレーターでハッシュを生成、UUIDジェネレーターでUUIDを作成できる。どちらも16進数出力だ。

Base 16を超えて:Base 36、Base 64、カスタム基数

標準の4つの基数でほとんどの仕事はカバーできるが、特殊な文脈で他の基数も登場する。

Base 36——コンパクトな英数字エンコーディング

Base 36は数字10個と英字26文字(A-Z)を使い、大文字小文字を区別しない英数字表現として最もコンパクトだ。URL短縮サービスでよく使われる——YouTubeの動画ID、短縮リンク、データベースの短いキーなどだ。

(1000000).toString(36)    // 'lfls'
parseInt('lfls', 36)      // 1000000

10進数1,000,000がたった4文字に。URL向けの短い識別子としてこれ以上コンパクトにするのは難しい。

Base 64——データエンコーディング(数値体系ではない)

Base64は別の基数のように見えるが、目的が異なる。数値を位取り記数法で表すのではなく、任意のバイナリデータ(画像、ファイル、JWTトークン)をASCIIテキストにエンコードする仕組みだ。A-Z、a-z、0-9、+/ の64シンボルを使う。

Base64は3バイト(24ビット)を4文字の6ビット単位に変換する。エンコーディングスキームであり、数値体系ではない。Base64のエンコード・デコードにはBase64エンコーダー&デコーダーを使おう。

任意の基数(2-36)が登場する場面

他にもいくつかの基数が現れる:

  • Base 12(十二進法): 時間(12時間制)、数量(1ダース)。12は10より約数が多いため、日常使用にはBase 12の方が優れているという数学者もいる。
  • Base 60(六十進法): 時間(60秒、60分)と角度(360°)。バビロニア数学から受け継がれた。
  • Base 32: Crockford Base32エンコーディング。人間が読みやすい識別子用で、I・L・Oなど紛らわしい文字を除外する。ジオハッシュにも使われる。

基数変換ツールは2から36までの任意の整数基数をサポートしている。

ビット演算と基数変換

2進数の理解は数値変換だけでなく、システムプログラミング、ゲーム開発、パーミッションシステムで頻出するビット演算の土台でもある。

const READ  = 0b100;  // 4
const WRITE = 0b010;  // 2
const EXEC  = 0b001;  // 1

// ORでパーミッションを結合
const perms = READ | WRITE;  // 0b110 = 6

// ANDでパーミッションを確認
(perms & READ)  !== 0   // true  — 読み取り権限あり
(perms & EXEC)  !== 0   // false — 実行権限なし

// XORでパーミッションを切り替え
perms ^ WRITE   // 0b100 = 4 — 書き込み権限を除去

// シフト演算
1 << 3    // 0b1000 = 8(1を左に3ビットシフト)
0xFF >> 4  // 0b00001111 = 15(右に4ビットシフト = 16で割る)

フィーチャーフラグ、ハードウェアレジスタ、ネットワークプロトコル、グラフィックスプログラミング——すべてビット演算に依存している。2進数を流暢に読めるようになれば、ビット操作は魔法ではなく明快なロジックに変わる。

FAQ

プログラミングで使われる主な4つの基数は?

2進数(Base 2)、8進数(Base 8)、10進数(Base 10)、16進数(Base 16)。2進数はハードウェア内のデータの物理的な存在形式。8進数はUnixファイルパーミッション用。10進数は人間向けのデフォルト。16進数は2進数を読みやすく圧縮する——16進1桁がちょうど4ビットに対応する。

2進数を16進数に変換するには?

右から4ビットずつグループ化し、左端が不足すればゼロで埋める。各グループを対応表で変換:0000=0、0001=1、……1010=A、……1111=F。例:2進数 10101111 → グループ 1010 1111 → 16進数 AF。16 = 2⁴ だから成り立つ。

16進数を10進数に変換するには?

各16進桁に16のその桁乗を掛けて合計する。A=10、B=11、C=12、D=13、E=14、F=15。例:16進数 FF = 15×16¹ + 15×16⁰ = 240 + 15 = 255。コード:JavaScript parseInt('FF', 16)、Python int('FF', 16)

開発者が2進数ではなく16進数を使う理由は?

16進数はコンパクトだ。16進1桁がちょうど4ビットに対応するため、2進数の 11111111 00001010 は16進数で FF0A になる。短くて読みやすい。メモリアドレス、CSSカラー(#FF5733)、MACアドレス、ハッシュ出力、UUIDフォーマットの標準表記として使われている。

ニブルとは何か。16進変換との関係は?

ニブルは4ビットのグループ、つまりバイトの半分。1ニブルがちょうど1つの16進桁に対応するため、2進数から16進数への変換はニブルごとの対照表参照で完了する。1バイト = 2ニブル = 16進2桁。この整った4ビット対応が、16進数がバイトレベルデータの標準表現になった理由だ。

Unixファイルパーミッションが8進数表記なのはなぜ?

各パーミッショングループには3ビットある:読み取り(4)、書き込み(2)、実行(1)。グループは3つ(所有者、グループ、その他)。2³ = 8 なので、3つのパーミッションビットが1つの8進桁にちょうど対応する。755 は所有者=7(rwx)、グループ=5(r-x)、その他=5(r-x)。8進数は3ビットグルーピングにとって自然な基数だ。

JavaScriptで2⁵³を超える数値を扱うには?

BigInt を使う。リテラルに n を付けるか、BigInt() コンストラクタを使用する:BigInt('0xFFFFFFFFFFFFFFFF').toString(2) で完全な64ビット2進数文字列が得られる。標準の Number は 9,007,199,254,740,991(2⁵³ - 1)を超えると精度が落ちる。基数変換ツールは内部でBigIntを使用しており、どんなサイズの数値でも精度を失わない。

16進数を2進数に変換するには?

ニブル対応表を逆引きして、各16進桁を4ビット2進数に展開する。0=00001=0001、……、A=1010、……、F=1111。例:16進数 AFA1010)+ F1111)→ 2進数 10101111。コード:JavaScript parseInt('AF', 16).toString(2)、Python bin(int('AF', 16))[2:]

Pythonの bin() とNumPyの numpy.base_repr() はどう違うか?

組み込みの bin()hex()oct() は整数専用で、プレフィックス付き文字列を返す(bin(10)'0b1010')。NumPyの numpy.base_repr(n, base) はプレフィックスなしの文字列を返し、任意の基数(2〜36)に対応する(np.base_repr(10, 2)'1010')。科学計算や配列全体を一括変換する場合は numpy.base_repr をベクトル化ラッパー経由で使うと高速だが、単発の変換には組み込み関数のほうが依存もなく簡潔。