こんにちは、MSKです。
今回は数字の表し方であるn進数について解説します。
プログラミングを行う上でも大切な考え方になります。

数字の表し方について考えてみよう

普段使っている数字 ~ 10進数 ~

普段僕たちは次のように数字を数えます。

1,2,3,4,5,6,7,8,9,10,11,12,13, … , 98,99,100,101, …

この数字の並びを見て思うことの1つに9の次で桁が上がっているということです。

1つの桁に出てくる数字は$0,1,2,3,4,5,6,7,8,9$の10個です。

このように10で桁上がりをしているような表記を10進数表記といいます。

0と1の世界 ~ 2進数 ~

2で桁上がりする表記方法は有名ですね。

2になると次の桁に進む数字の表記方法を2進数表記と言います。

2進数では各桁に0と1しか現れません。

コンピューターは内部で2進数を使用しています。

なぜ2進数が使われるのかを簡単に説明するとコンピューターの内部は電子回路の集まりになっていますが、その電子回路では電圧がかかっているか・かかっていないかの2つの状態があります。

電圧がかかっている状態を1、かかっていない状態を0とできるので、コンピューターでは2進数が扱いやすいのです。

例

10進数 → 2進数と対応させてみたいと思います。

0 → 0
1 → 1
2 → 10
3 → 11
4 → 100

2進数であることを強調したい場合は通常0bを数値の先頭につけます。
例えば、0b1001001のような感じです。

コンピューターと相性がよい ~ 8進数,16進数 ~

2進数と同じように8で桁上がりする表記を8進数表記、16で桁上がりする表記を16進数表記といいます。

16進数の場合、9の次は次のように並びます。
A、B、C、D、E、F

例

2進数のときと同じように10進数と対応をつけたいと思います。
①10進数 → 8進数
6 → 6
7 → 7
8 → 10
9 → 11
・・・・・
63 → 77
64 → 100
65 → 101

②10進数 → 16進数
9 → 9
10 → A
11 → B
12 → C
13 → D
14 → E
15 → F
16 → 10
17 → 11
・・・・・
254 → FE
255 → FF
256 → 100

8進数であることを強調したい場合は通常0oを、16進数であることを強調したい場合は通常0xを数値の先頭につけます。
例えば、0o7654321、0xABCD01のような感じです。

※なぜ、2進数は0b、8進数は0o、16進数は0xなのかというと、Binary(英語で2進数)、Octal(英語で8進数)、Hexadecimal(英語で16進数)の頭文字からきています。

8進数・16進数はコンピューターと相性が良いです。

上でコンピューターでは2進数が使われていると書きました。
8進数の一桁を2進数でみるとちょうど3桁分になっています。
 8進数の一桁 = 0b000 ~ 0b111(=7)
昔のコンピューターは2進数12桁、または24桁で処理されるものが多く、3桁の表記を持つ8進数との相性が良いとされていました。

16進数の一桁も2進数でみるとちょうど4桁分になっています。
 16進数の一桁 = 0b0000 ~ 0b1111(=15)
現在のコンピューターは2進数の32桁、または64桁で処理されるものが多く、4桁の表記を持つ16進数と相性が良いです。

ビット・バイトやコンピュータサイエンスでよく使われる単位について

1ビット(bit)は2進数の1桁のことを言います。
例えば、0b110は3ビット持っています。

8ビットを1つの単位とみなしたものがバイト(byte)という単位になります。
コンピューターの世界でよく目にするバイトはこのことです。
1バイトで0から255の256個の表現ができます。

コンピューターサイエンスでよく使われる単位をまとめておきます。

ピコ(p) = 10^{-12}
ナノ(n) = 10^{-9}
マイクロ(μ) = 10^{-6}
ミリ(m) = 10^{-3}

キロ(k) = 10^3 \fallingdotseq 2^{10}
メガ(M) = 10^6 \fallingdotseq 2^{20}
ギガ(G) = 10^9 \fallingdotseq 2^{30}
テラ(T) = 10^{12} \fallingdotseq 2^{40}

n進数

今まで見てきたことからn進数はnで桁上がりする表記です。
各桁に出てくる数字は0からn-1までです。

n進数表記のnを基数といいます。
各桁に出てくる数値は0からn-1までのn個なので、基数とは各桁に出てくる数値の個数とも言えます。

基数変換

ある基数の表示から別の基数の表記へ変換することを考えていきたいと思います。

10進数をもう一度眺めてみる

10進数で次の数字を考えてみます。

1234.567

これは次にように表記できます。

1 \times 10^3 +2 \times 10^2 +3 \times 10^1 +4 \times 10^0 +5 \times 10^{-1} +6 \times 10^{-2} +7 \times 10^{-3}

もとの数字は(各桁の数字) \times 10^{~}を全部足したものになっています。
~は整数部分では桁数-1で、小数部分では小数第p位だとすると-pとなります。

これはn進数で表したときも同じように表記でき、10^{~}となっている部分が(基数)^{~}となります。
(実際、10進数の場合もこのようになっていますね)

この(基数)^{~}をその桁の重みといいます。

n進数で表された数値を10進数に変換する際はこの内容を使用します。
具体的に見ていきましょう。

2進数から10進数に変換してみよう

例

0b101101.101を考えます。

上で述べたことから、次のように表せます。

1 \times 2^5 +1 \times 2^3 +1 \times 2^2 +1 \times 2^0 +1\times 2^{-1} +1 \times 2^{-3} = 32 + 8 + 4 + 1 + 0.5 + 0.125 = 45.625

問題も書いておきたいと思います。

問題1

次の2進数を10進数に変換してください。

(1) 0b1011.011

(2) 0b10001.11

8進数・16進数から10進数に変換してみよう

まずは8進数から10進数に変換します。

例

0o137.246を考えます。

2進数のときと同様に

0o137.246 \\ =1 \times 8^2 +3 \times 8^1 +7 \times 8^0 +2 \times 8^{-1} +4 \times 8^{-2} +6 \times 8^{-3} \\ = 64 + 24 + 7 + 0.25 + 0.0625 + 0.01171875 \\ =95.32421875

問題2

次の8進数を10進数に変換してください。

(1) 0o37.117

(2) 0o2167.62

次に16進数から10進数へ変換します。

例

0xA1C.6E \\ = 10 \times 16^2 +1 \times 16^1 +12 \times 16^0 +6 \times 16^{-1} +14 \times 16^{-2} \\ = 2560 + 16 + 12 + 0.375 + 0.0546875 \\ = 2588.4296875

問題3

次の16進数を10進数に変換してください。

(1) 0xF2.A7

(2) 0x3FA.F2

10進数からn進数に変換してみよう

10進数からn進数に変換する手順は以下になります。

  1. 10進数表示された数値の整数部分と少数部分に分けます。
  2. 整数部分は基数で割り、商と余りを出します。
  3. その商をまた基数で割り、商と余りを出します。
    これを商が0になるまで行います。
  4. 出てきた余りを出てきた順番とは反対に並べると整数部分のn進数表記になります。
  5. 少数部分は基数をかけて出てきた数値の整数部分を取り出します。
  6. 残った数値にまた基数をかけて、同じことを繰り返します。
  7. 少数部分がなくなったらそこまで出てきた整数部分を順番に並べると少数部分のn進数表記になります。
  8. 整数部分と少数部分を組み合わせて、全体のn進数表記ができあがります。

例で見ていきたいと思います。

例

34.8125を2進数表記にしたいと思います。

  1. 整数部分は34、少数部分は0.8125です。
  2. 34を基数の2で割ります。
    34 \div 2 = 17 余り 0
  3. 17 \div 2 = 8 余り 1
    8 \div 2 = 4 余り 0
    4 \div 2 = 2 余り 0
    2 \div 2 = 1 余り 0
    1 \div 2 = 0 余り 1
  4. 出てきた余りを出てきた順番と逆に並べると100010
  5. 少数部分の0.8125に基数の2をかけます。
    0.8125 \times 2 = 1.625 整数部分 1
  6. 0.625 \times 2 = 1.25 整数部分 1
    0.25 \times 2 = 0.5 整数部分 0
    0.5 \times 2 = 1.0 整数部分 1
  7. 出てきた整数部分を順番に並べると1101
  8. 34.8125を2進数に変換すると100010.1101となります。
問題4

(1) 10進数の13.75を2進数表記してください。

(2) 10進数の34.8125を8進数表記してください。

(2) 10進数の34.8125を16進数表記してください。

2進数と8進数・16進数の間の変換

2進数から8進数・16進数の変換は簡単です。
上で8進数の一桁は2進数の3桁、16進数の一桁は2進数の4桁になると書きました。
これを使います。

例

2進数表記の0b1010.10を考えます。

8進数に変換する場合は整数部分と少数部分に分けて、それぞれ3桁で区切ります。
整数部分1010は、001と010です。
少数部分は100です。
これらをそれぞれ8進数に変換します。
001=1
010 = 2
100 = 4
あとはこれらを順番に並べて、12.4が8進数に変換した表記になります。

16進数もほとんど同じで8進数では3桁区切りだったところを4桁区切りにします。
整数部分は1010、少数部分は1000です。
これらを16進数に変換します。
1010 = A
1000 = 8
これらを並べるとA.8になり、これが0b1010.10を16進数表記したものになります。

問題5

次の2進数を8進数と16進数の表記にしてください。

(1) 0b1001.011

(2) 0b110.1011

8進数・16進数から2進数への変換も簡単です。
2進数から8進数・16進数への変換と逆を行います。

8進数・16進数の各桁の数値を2進数にして、並べるだけです。

例

(1) 0o64.71を2進数表記します。

6 = 0b110
4 = 0b100
7 = 0b111
1 = 0b001
なので、0o64.71は2進数で0b110100.111001とかけます。

(2) 0xD71.BFを2進数表記します。

D = 0b1101
7 = 0b0111
1 = 0b0001
B = 0b1011
F = 0b1111
なので、0xD71.BFは2進数で0b110101110001.10111111とかけます。

問題6

次を2進数表記にしてください。

(1) 0o32.65

(2) 0x4A.C9

まとめ

n進数、特に2進数、8進数、16進数について表記の方法や基数変換をたくさんの例を使って解説してきました。
基本情報技術者試験を受ける人は知っておかないといけない知識になります。

また、組み込み系のエンジニアを目指している方は2進数、16進数を扱えることは必須になります。

以上、「n進数を理解しよう!」でした。
最後までご覧頂き、ありがとうございます。

問題の回答

ABOUT ME
MSK
数学・プログラミング・ゲーム制作が大好きな30代エンジニア。 趣味でUnityやC言語を使って数学を可視化したり、小さなアプリを作ったりしています。 教育・学びの楽しさにも関心があります。