組み込みをやっているとよく遭遇する、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の左側です。
- 10進数xを10で除算し、商をとる
- 1.の結果を0x0fとANDをとり、xの十の位の値のみ抜き出す
xの値が123のとき、10で割った商は12となり、2は不要 - 2.の結果を4ビット左にシフトする
これは2進化10進数では10倍することと同じ
次はORの右側です。
- 10進数xを10で除算し、余りをとる
- 4.の結果と0x0fとANDをとり、xの一の位の値のみを抜き出す
ここの手順は不要かもしれませんが、安全に計算します
最後にORです。
- 3.の結果と5.の結果をORとることで、10進数の下二桁だけを2進化10進数に変換する
以下のようなイメージ????0000 | 0000!!!! → ????!!!!
BCD2DEC
#define BCD2DEC(x) ((x >> 4) & 0x0f) * 10 + (x & 0x0f)
同様に+の左側からです。
- 2進化10進数xを4ビット右にシフトする
- 1.の結果を0x0fとANDをとり、4ビット目から7ビット目だけを抜き出す
7ビット目より上位ビットが入っても、打ち消す - 2.の結果を10で乗算し、10進数の十の位の値を計算する
次に+の右側です。
- 2進化10進数xを0x0fとANDをとり、0ビット目から4ビット目だけを抜き出す
これで10進数の一の位の値を計算できる(1を乗算してもよい)
最後に+です。
- 3.の結果と4.の結果を和算し、2進化10進数の0ビット目から7ビット目だけを10進数に変換する
おわりに
ビット演算がまだまだなれていないので、どうしても複雑な計算式にしてしまいがちです。
しかしビット演算がなれると、if文が入りそうな計算式でも1式で表現できるので、便利ですね。
さくっとできるようになりたいです。
参考になれば幸いです(^^)