ari23の研究ノート

メーカ勤務エンジニアの技術ブログです

2進化10進数と10進数の関係

組み込みをやっているとよく遭遇する、2進化10進数(BCD)とその変換方法についてまとめます🐜

ビット演算に慣れていない自分の備忘録がメインです。1

2進化10進数とは?

英語ではBinary-coded decimal(BCD)といい、10進の0~9を4ビット(2進数)で表現する方法です。2

言葉だけではわかりずらいので、ここでは具体的に10進数(Decimal, DEC)と2進化10進数を比べてみます。

10進(DEC) 2進化10進(BCD)
0 0000 0000
1 0000 0001
2 0000 0010
3 0000 0011
4 0000 0100
5 0000 0101
6 0000 0110
7 0000 0111
8 0000 1000
9 0000 1001
10 0001 0000
20 0010 0000
40 0100 0000
80 1000 0000
59 0101 1001

上記の表を見ると、2進数の1010以上は使わず、次の4ビットを使って表現することがわかります。

つまり、各ビットに下記のような値(DEC)の役割があると考えてもよいです。

7bit目 6bit目 5bit目 4bit目 3bit目 2bit目 1bit目 0bit目
80 40 20 10 8 4 2 1

2進化10進数↔10進数の変換式

で、ここから本題。
じゃあ、この2進化10進数と10進数の変換をどうやってやるのか。

2進化10進数から10進数に変換するときは、各ビットの0, 1を判定して、足し算する?

10進数から2進化10進数に変換するときは、10で割った商と余りを2進数にして足し算する?

普通にやるとめんどくさい計算になりそうですが、ビット演算をうまくやると、どちらもif文なしの1つの式で計算できます。

#define DEC2BCD(x)  ((x / 10) & 0x0f) << 4 | ((x % 10) & 0x0f)
#define BCD2DEC(x) ((x >> 4) & 0x0f) * 10 + (x & 0x0f)

なお、今回は簡単のため、10進で二桁の値のみ(つまり0~99まで)を対象とします。

解説

下の表を使いながら解説します。

A B A ∩ B A ∪ B
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 1

DEC2BCD

#define DEC2BCD(x)  ((x / 10) & 0x0f) << 4 | ((x % 10) & 0x0f)

まずORの左側です。

  1. 10進数xを10で除算し、商をとる
  2. 1.の結果を0x0fとANDをとり、xの十の位の値のみ抜き出す
    xの値が123のとき、10で割った商は12となり、2は不要
  3. 2.の結果を4ビット左にシフトする
    これは2進化10進数では10倍することと同じ

次はORの右側です。

  1. 10進数xを10で除算し、余りをとる
  2. 4.の結果と0x0fとANDをとり、xの一の位の値のみを抜き出す
    ここの手順は不要かもしれませんが、安全に計算します

最後にORです。

  1. 3.の結果と5.の結果をORとることで、10進数の下二桁だけを2進化10進数に変換する
    以下のようなイメージ

    ????0000 | 0000!!!! → ????!!!!

BCD2DEC

#define BCD2DEC(x)  ((x >> 4) & 0x0f) * 10 + (x & 0x0f)

同様に+の左側からです。

  1. 2進化10進数xを4ビット右にシフトする
  2. 1.の結果を0x0fとANDをとり、4ビット目から7ビット目だけを抜き出す
    7ビット目より上位ビットが入っても、打ち消す
  3. 2.の結果を10で乗算し、10進数の十の位の値を計算する

次に+の右側です。

  1. 2進化10進数xを0x0fとANDをとり、0ビット目から4ビット目だけを抜き出す
    これで10進数の一の位の値を計算できる(1を乗算してもよい)

最後に+です。

  1. 3.の結果と4.の結果を和算し、2進化10進数の0ビット目から7ビット目だけを10進数に変換する

おわりに

ビット演算がまだまだなれていないので、どうしても複雑な計算式にしてしまいがちです。
しかしビット演算がなれると、if文が入りそうな計算式でも1式で表現できるので、便利ですね。
さくっとできるようになりたいです。

参考になれば幸いです(^^)


  1. RTC使うときよく出てくるみたい。というか出てきて混乱したw

  2. 近似値になるのを防ぐ方法で、銀行システムでよく使われるようです。