
C言語基礎|10進数の基数変換
10進数は人間にとって自然だけど、コンピュータの世界では 2進数・8進数・16進数が日常茶飯事です。
そこで大事になるのが、10進数を別の基数に変換する手順。やり方は意外とシンプルで、
- 目的の基数で割る。
- 剰余を集める。
- 逆順に並べる。
この3点セットで完成します。
ここでは 2進数・8進数・16進数への変換を、表と図で「同じ仕組み」として整理していきますね。

10進数 → n進数は割り算が主役
10進数を n進数に変換するときの核はこれです。
10進数 → n進数の基本手順
| 手順 | すること | 意味 |
|---|---|---|
| 1 | 10進数を n で割る | n進数の右に1桁ずらすイメージ |
| 2 | 剰余を記録する | 剰余が最下位桁になる |
| 3 | 商を次の入力にして繰り返す | 商が 0 になるまで続ける |
| 4 | 剰余を逆順に並べる | 上位桁からの表現が完成 |
この表のポイントは「剰余が下の桁」になること。だから逆順にする必要があるんです。
10進数 57 を 2進数に変換する
2で割り続けて剰余を集め、最後に逆順です。
57 → 2進数(割り算と剰余)
| 割る前 | 割る | 商 | 剰余 |
|---|---|---|---|
| 57 | 2 | 28 | 1 |
| 28 | 2 | 14 | 0 |
| 14 | 2 | 7 | 0 |
| 7 | 2 | 3 | 1 |
| 3 | 2 | 1 | 1 |
| 1 | 2 | 0 | 1 |
剰余を上から書くと 1 0 0 1 1 1
逆順に読むので 111001(これが 57 の 2進表現)になります。
10進数 57 を 8進数に変換する
やることは同じで、割る数が 8 になるだけです。
57 → 8進数
| 割る前 | 割る | 商 | 剰余 |
|---|---|---|---|
| 57 | 8 | 7 | 1 |
| 7 | 8 | 0 | 7 |
剰余を逆順に並べて 71(8進数)です。
10進数 57 を 16進数に変換する
16で割ると、剰余が 10〜15 になることがあるので、そこだけ注意。
57 → 16進数
| 割る前 | 割る | 商 | 剰余 |
|---|---|---|---|
| 57 | 16 | 3 | 9 |
| 3 | 16 | 0 | 3 |
逆順で 39(16進数)です。
16進数の剰余が文字になる対応
| 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|
| A | B | C | D | E | F |
この表は「剰余が10以上になったら文字になる」を確認するためのものです。
2進数と16進数/8進数はまとめて変換できる
ここ、気持ちいいところです。
2進数は桁数が長くなりがちなので、読みやすくするために 16進数や 8進数に「まとめて変換」することが多いです。
- 2進数4桁 ↔ 16進数1桁
- 2進数3桁 ↔ 8進数1桁
2進数4桁と16進数1桁の対応(抜粋)
| 2進数 | 16進数 | 2進数 | 16進数 |
|---|---|---|---|
| 0000 | 0 | 1000 | 8 |
| 0001 | 1 | 1001 | 9 |
| 0010 | 2 | 1010 | A |
| 0011 | 3 | 1011 | B |
| 0100 | 4 | 1100 | C |
| 0101 | 5 | 1101 | D |
| 0110 | 6 | 1110 | E |
| 0111 | 7 | 1111 | F |
4桁ごとに区切るだけ(2進 → 16進)
0111 1010 0101 1100
7 A 5 C
この図の意味は「計算しなくても置き換えるだけで済む」ということ。現場でも超よく使います。
C言語で基数変換を試す
「10進数を入力すると、2進・8進・16進をまとめて表示する」プログラムです。
プロジェクト名:chap7-4-1 ソースファイル名:chap7-4-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 10進数を 2進数 / 8進数 / 16進数 に変換して表示する
#include <stdio.h>
void print_in_base(unsigned int value, unsigned int base)
{
char buf[33];
const char digits[] = "0123456789ABCDEF";
int idx = 0;
if (value == 0) {
putchar('0');
return;
}
while (value > 0) {
unsigned int r = value % base;
buf[idx++] = digits[r];
value /= base;
}
for (int i = idx - 1; i >= 0; i--) {
putchar(buf[i]);
}
}
int main(void)
{
unsigned int n;
puts("10進数を入力すると、2進・8進・16進に変換して表示します。");
printf("入力してください(0以上): ");
scanf("%u", &n);
printf("2進数 : ");
print_in_base(n, 2);
putchar('\n');
printf("8進数 : ");
print_in_base(n, 8);
putchar('\n');
printf("16進数 : ");
print_in_base(n, 16);
putchar('\n');
return 0;
}登場する命令の書式と「何をするか」
puts
- 書式:puts(文字列);
- 何をする:文字列を表示して改行する(案内文に便利)
printf
- 書式:printf(書式文字列, 値, ...);
- 何をする:書式付きで表示する(ラベルや整形表示)
scanf
- 書式:scanf(書式文字列, 変数のアドレス);
- 何をする:入力を読み取る
・%u は unsigned int 用
・&n のように「格納先」を渡す
putchar
- 書式:putchar(文字);
- 何をする:1文字だけ出力する(変換結果を1桁ずつ出すのに最適)
% と /
- value % base:剰余を求める(最下位桁)
- value /= base:商に更新する(次の桁へ)
表と図でプログラムの動きを説明する
print_in_base の中で起きていること
| 処理 | 目的 | 例(n=57, base=2) |
|---|---|---|
| r = value % base | 最下位桁を取り出す | 57 % 2 → 1 |
| buf に r を入れる | 下位桁からためる | buf に 1 |
| value /= base | 次の計算へ | 57 / 2 → 28 |
| 逆順で出力 | 表示は上位桁から | 111001 |
バッファに逆順でたまる
剰余が出る順: 1, 0, 0, 1, 1, 1
bufの中 : [1][0][0][1][1][1]
表示 : 111001 (逆から出す)
