8 ビット（255）までの 2 or 16 進数を 5 秒以内で 10 進数に暗算する方法（練習アプリ付き）

10 年くらい 8 ビットまでの基数変換は暗算して対処してきたのですが、意外にこの辺りの計算を苦手とするエンジニアが結構多いんじゃないかと思ったので、速く計算する方法を紹介してみることにしました。

アイデア自体は [計算力を強くする, 鍵本　聡 (2005)](https://bookclub.kodansha.co.jp/product?item=0000194454) の第１章、「かけ算は計算力の基本」から拝借しています。

# よくある基数変換の解説

前提として、教科書などで紹介されている計算方法を説明します。
知っている人は読み飛ばしてください。

## 2 進数の場合

2 進数から 10 進数への一般的な計算方法は、各桁の値に 2 の累乗をかけて、それを合計します。
右から左に向かって、2の0乗、1乗、2乗...と増えていきます。

例えば「1101」を 10 進数に変換する場合は以下のようになります。

```text:2 進数の計算過程
一番右の「1」: 1 × 2⁰ = 1 × 1 = 1
その左の「0」: 0 × 2¹ = 0 × 2 = 0
その左の「1」: 1 × 2² = 1 × 4 = 4
その左の「1」: 1 × 2³ = 1 × 8 = 8

これらを全て足し合わせると、 10 進数の値が計算できます。
1 + 0 + 4 + 8 = 13
```

文字だと覚えづらいので、絵も描いてみました。

```mermaid
%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#2c3e50',
    'primaryTextColor': '#ecf0f1',
    'primaryBorderColor': '#34495e',
    'lineColor': '#95a5a6',
    'secondaryColor': '#34495e',
    'tertiaryColor': '#ecf0f1'
  }
}}%%

graph LR
    classDef binary fill:#2c3e50,stroke:#34495e,stroke-width:2px,color:#ecf0f1,font-weight:bold
    classDef position fill:#34495e,stroke:#2c3e50,stroke-width:2px,color:#ecf0f1
    classDef calculation fill:#445566,stroke:#34495e,stroke-width:2px,color:#ecf0f1
    classDef result fill:#1a1a1a,stroke:#34495e,stroke-width:2px,color:#ecf0f1,font-weight:bold

    subgraph Binary["2進数 1101"]
        A1[1]:::binary --> B1[2³ = 8]:::position
        A2[1]:::binary --> B2[2² = 4]:::position
        A3[0]:::binary --> B3[2¹ = 2]:::position
        A4[1]:::binary --> B4[2⁰ = 1]:::position
    end

    subgraph Calc["計算過程"]
        B1 --> C1[8 × 1 = 8]:::calculation
        B2 --> C2[4 × 1 = 4]:::calculation
        B3 --> C3[2 × 0 = 0]:::calculation
        B4 --> C4[1 × 1 = 1]:::calculation
    end

    subgraph Result["10進数"]
        C1 & C2 & C3 & C4 --> D[13]:::result
    end

    style Binary fill:#f8f9fa,stroke:#34495e,stroke-width:1px
    style Calc fill:#f8f9fa,stroke:#34495e,stroke-width:1px
    style Result fill:#f8f9fa,stroke:#34495e,stroke-width:1px
```

## 16 進数の場合

16 進数は、 0 から 15 までの数字を表すのに以下の 16 個の文字を使います。

```text:16 進数の一覧
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A(10), B(11), C(12), D(13), E(14), F(15)
```

計算方法は 2 進数と同じ発想ですが、各桁の値に 16 の累乗をかけて合計することで 10 進数に変換できます。
右から左に向かって、16 の 0 乗（=1）、1乗（=16）、2乗（256）...と増えていきます。

例えば「12A」を 10 進数に変換する場合は以下のようになります。

```text:16 進数を計算する過程
一番右の「A」: A ×  16⁰ = 10 ×   1 = 10
その左の「2」: 2 ×  16¹ =  2 ×  16 = 32
その左の「1」: 1 × 256² =  1 × 256 = 256

これらを全て足し合わせると、 10 進数の値が計算できます。
10 + 32 + 256 = 298
```

# 九九の原理で速くする

教科書通りの計算方法では、 2 進数であれば 2 の累乗を足し合わせ、16 進数であれば 16 の累乗を足し合わせていました。
ただ、上記の方法を比べると、 16 進数の方が 10 進数への計算が速くしやすいです。

まず、 A~F まで対応する数値を覚え、16 x 1 ~ 16 までの計算結果を覚えておけば、8 ビット（255）までの計算は容易になることがわかります。

```text:154 の 16 進数を計算する過程
9A = 16 * 9 + 10 = 144 + 10 = 154
```

これが 2 進数の場合は以下のように計算が多くなります。

```text:154 の 2 進数を計算する過程
1001 1010 = 2⁷ + 2⁴ + 2³ + 2¹ = 128 + 16 + 8 + 2 = 154
```

2 の累乗を 2¹ から 2⁷ まで暗記すれば、足し算までは簡単に持っていけますが、足し算の項が多くなって暗算するには面倒です。

そこで、 2 進数も 16 進数と同様、16 の累乗で計算することにします。
そのためには、16 パターンの 01 の並びから 10 進数に変換する必要がありますが、そこは九九と同様、暗記で対処します。

では、下の表を暗記します。

| 2進数 | 16進数 | 10進数 | 16を掛けた値(10進数) |
|-------|---------|--------|---------------------|
| 0000  | 0       | 0      | 0                   |
| 0001  | 1       | 1      | 16                  |
| 0010  | 2       | 2      | 32                  |
| 0011  | 3       | 3      | 48                  |
| 0100  | 4       | 4      | 64                  |
| 0101  | 5       | 5      | 80                  |
| 0110  | 6       | 6      | 96                  |
| 0111  | 7       | 7      | 112                 |
| 1000  | 8       | 8      | 128                 |
| 1001  | 9       | 9      | 144                 |
| 1010  | A       | 10     | 160                 |
| 1011  | B       | 11     | 176                 |
| 1100  | C       | 12     | 192                 |
| 1101  | D       | 13     | 208                 |
| 1110  | E       | 14     | 224                 |
| 1111  | F       | 15     | 240                 |

この要領で 256 の段も暗記すれば、12 ビット（4096）まで暗算できるようになりますが、その場合足し算が面倒になるのと、情報処理技術者試験で出題される問題はほとんど 255 まで計算させる範囲しか出題されないようなので、私はトライしてないです。

# あとは練習あるのみ

上記の表をある程度覚えたら、あとは練習あるのみです。
練習アプリを雑に作ったので、以下の Web アプリで遊んでいけば、すぐマスターできると思います！

https://nimzo6689.github.io/number-conversion-quiz/

10 問出題されるので、 50 秒切れれば本記事のタイトル通り、5 秒以内で解けていることになります。
厳密にはタイピングの時間もありますが、皆さん速いのでそのような時間はないものとしています。

一応、エビデンス貼っておきます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/618a306f-d80c-85f2-210c-563135b8bd67.png)