【C言語(1)】2進数と16進数
C言語学習の最初の記事ですが、この記事ではプログラムコードは出てきません。
まずは基礎固め。プログラマの共通知識を習得しましょう。
最後に問題も用意していますので、理解度の確認に役立ててください。
2進数とは何者か
分かった気になる説明はこれ
私たちが普段数えるときに使っているのは10進数と呼ばれ、『0〜9』の10個の数字で数値を表す方法です。9に1を足すと繰り上がって10(じゅう)となるお馴染みのやつです。
これに対し、2進数とは『0』と『1』の2個の数字だけで数値を表す方法です。1に1を足すと繰り上がって10(いちぜろ)となります。(じゅう)じゃありません。(いちぜろ)です。
その後も順に1を足していくと、
10 → 11 → 100 → 101 → 110 → 111 → 1000 → ・・・
といった具合に増えていきます。
10進数と比較すると次の通りです。
10(2進数) = 2(10進数)
11(2進数) = 3(10進数)
ところで、なんで2進数が必要なの?
大体僕らは10進数で数えることに慣れてるんだし、なんで今さらそんなややこしい数え方すんだよ。
10進数使えば良いじゃん!10進数!
初めて2進数を勉強したときはそう思ってました。
ところが、どうやらマイコンのプログラムを書くのに10進数では都合が悪い時があるということが分かりました。
つまり、『プログラムを書くにあたって、2進数の方が10進数よりも都合が良い場合がある』というのが2進数を必要とする理由です。
マイコンはどうやって動いてる?
突然ですが、マイコンの説明を少し挟ませてください。
マイコンには特定の機能を持った機器*1が多数内蔵されています。詳しくはマイコンの章でお話ししたいと思いますが、簡単に描くとこんな感じです。
プログラムをマイコンに書き込むと、CPUがそのプログラム通りに動いてくれます。
実際にはマイコンに内蔵されているメモリにプログラムが書かれ、CPUがメモリからプログラムを読み出すことで動いています。
このメモリ、実は数十~数百万個のスイッチで構成*4されています。
スイッチにはONとOFFの2つしかありません。
つまりCPUは各スイッチからONかOFFを読み出して動いているわけです。
そのスイッチの組み合わせで数値を表現しています。
例えばスイッチが1つしかなければ、表現できる総数は0(OFF)、1(ON)の2通りです。
スイッチが2つあるのであれば、その組み合わせ総数は00、01、10、11の4通り。10進数でいうところの0、1、2、3です。
スイッチが3つあるのであれば、その組み合わせ総数は000、001、010、011、100、101、110、111の8通りです。10進数でいうところの0、1、2、3、4、5、6、7です。
マイコンのプログラムでは、このスイッチはON(1)にして、このスイッチはOFF(0)にして…と考えることが多いです。
どのスイッチをON(1)にして、どのスイッチをOFF(0)にするのかを考えるのに、2進数の方がダントツで理解しやすいですよね。
これが『2進数の方が10進数よりも都合が良い場合』の説明です。
16進数とは何者か
分かった気になる説明はこれ(2)
16進数は『0~9』の10個の数字と、『A~F』の6個のアルファベットを使って数値を表す表現法です。9に1を足すとAとなり、Aに1を足すとBとなります。そしてFに1を足すと繰り上がって10(いちぜろ)となります。
したがって、16進数の『0~F』は10進数の『0~15』に相当します。
2進数よりもさらに理解し難いヤツが出てきましたね。
2進数では書きません
『プログラムを書くにあたって、2進数の方が10進数よりも都合が良い場合がある』ことは前述のとおりです。
すみません、さっそく訂正させてください。早すぎやろ
正直、私の経験上プログラムで2進数を書くことはありません*5。
圧倒的に16進数もしくは10進数です。
やっぱり数値は10進数の方が理解しやすいので、数値についてはプログラムでも10進数で書きます。
ただ前述のとおり、どのスイッチをON(1)にして、どのスイッチをOFF(0)にするのかは2進数を使って考えます。考えるだけで、2進数では書きません。
16進数を使う理由
組み合わせるスイッチの数は8個だったり16個だったり、32個だったりするのが一般的です。ここは、そんなもんなんだと今は納得していただきたいです。
たとえば16個のスイッチの組み合わせを2進数で書くとどんな感じになるでしょうか。
1001111101011011
こんな感じです。
長い。そして何個目のスイッチが1で、何個目のスイッチが0なのかも分かりにくい。
ってかホントに16個ある?
32個のスイッチなんて書きたくないし、読みたくないし、考えたくもありません。
ここで、次の表を見てください。
この表は2進数、16進数、10進数の比較表です。変換表としても使えますね。
2進数 | 16進数 | 10進数 |
---|---|---|
0
|
0
|
0
|
1
|
1
|
1
|
10
|
2
|
2
|
11
|
3
|
3
|
100
|
4
|
4
|
101
|
5
|
5
|
110
|
6
|
6
|
111
|
7
|
7
|
1000
|
8
|
8
|
1001
|
9
|
9
|
1010
|
A
|
10
|
1011
|
B
|
11
|
1100
|
C
|
12
|
1101
|
D
|
13
|
1110
|
E
|
14
|
1111
|
F
|
15
|
10000
|
10
|
16
|
表の中で、16進数が0〜Fまで一巡すると同時に、2進数の4桁がちょうど一巡している事が分かるでしょうか。
これはつまり、16進数1桁で、2進数4桁を表す事ができるということです。
先ほど羅列した16桁の2進数を16進数に変換してみましょう。
こんなんでしたね。
1001111101011011
4桁ずつに分割します。16個ありましたね…
1001 1111 0101 1011
先の表を見て、16進数に変換します。
9F5B
スッキリしました!
16進数で4桁なので、2進数では16桁であることもすぐに理解できます。
プログラムでは2進数ではなく、この16進数を使って書くことが多いです。
2進数、16進数、10進数の対応は表を見なくても良いように、頭に叩き込んでおきましょう!*6
最初はややこしいですが、慣れれば一瞬で変換可能になります。
進数の表現法
1010 ← コレいくつ?
10進数では1010(せんじゅう)ですね。でも、もしかしたら2進数の1010(いちぜろいちぜろ)かもなぁ。。いやいや、16進数の1010(いちぜろいちぜろ)やろ。
ここで実は8進数*7でしたー、とかいう引っ掛けあるんちゃうん?
・・・・・。汗
10進数しか使ってなければ何も疑問に思いませんでしたが、2進数や16進数などを勉強すると「これは…?」と立ち止まってしまいますよね。
2進数の1010は10進数では10、16進数の1010は10進数では4112です。随分違いますね。
これでは困るので、数値が何進数なのか表現する方法を知っておきましょう。
表現法
10進数
10進数は一般的なので、文書でもプログラムでも普通に数字を書けば10進数という認識です。
ただ、この記事のように他の進数での表記があるなどして、10進数であることを意図的に明示したい場合には次のように表すことが出来ます。
1010(10)
(1010)10
0d1010
10進数は英語でdecimal(デシマル)と呼びます。0d(ぜろでぃー)のdはdecimalの頭文字です。
2進数
2進数を明示する場合には、次のように表すことが出来ます。
1010(2)
(1010)2
0b1010
2進数は英語でbinary(バイナリ)と呼びます。0b(ぜろびー)のbはbinaryの頭文字です。
16進数
16進数を明示する場合には、次のように表すことが出来ます。
1010(16)
(1010)16
1010'h・1010h・1010H
0x1010
16進数は英語でhexadecimal(ヘキサデシマル)と呼びます。hやH、0x(ぜろえっくす)のxはhexadecimalからとられたものです。C言語で16進数を記述する際には0xの表現を使用します。
会話で16進数の数値を話すときには、『16進の1010』や『HEX(へっくす)の1010』などと言うことが個人的には多いです。
16進の~やHEXの~など接頭語を付けた場合に限っては、1010(いちぜろいちぜろ)を間違えて1010(せんじゅう)と言ったとしても雰囲気で伝わります。ただ、接頭語もなしに1010(せんじゅう)と言えば、相手は確実に10進数と誤認識することになります。
理解度チェック
この記事の内容をおさらいしておきましょう。
【答えを表示】をクリックすると回答例を表示します。
(1)0b1101を16進数に変換してください。
0xD
((D)16、D(16)、D'h、Dh、DHでもOK!)
2進数4桁は、16進数1桁で表すことができるのでした。
(2)0xABCDを2進数に変換してください。
0b1010101111001101
((1010101111001101)2、1010101111001101(2)でもOK!)
16進数1桁につき、2進数4桁が変換されます。
16進数1桁ずつ、順番に2進数に変換しましょう。
(3)『0xC + 0b0011 - 5 』の計算式の答えを16進数で答えてください。
0xA
((A)16、A(16)、A'h、Ah、AHでもOK!)
0xCは12(10)、0b0011は3(10)です。
つまり、計算式を全て10進数で書くと『12 + 3 - 5』となり、答えは10(10)です。10(10)は0xAでしたね。
最後の問題で、計算式の答えがマイナスになった時にはどう答えれば良いのでしょうか。
ということで、次回は負数(マイナスの数)の表現法について解説します!
/*** このサイトでは脚注を豊富に記載します ***/
*1:特定の機能を持った機器:マイコンに内蔵されている機器の事を周辺機器と呼ぶ。英語ではperipheral(ペリフェラル)と呼ぶ。
*2:CPU:しーぴーゆー。Central Processing Unit(中央演算処理装置)と訳される。
*4:スイッチで構成:イメージしやすい表現としてスイッチとしている。ホントは数十~数百万個のトランジスタがぎゅっと集積されていて、それぞれのトランジスタのON/OFFを行うことでその1つ1つに電気を溜めたり放出したりして情報の保存が実現されている。
*5:2進数を書くことはありません:書くことは可能です。書かないだけで。
*6:頭に叩き込んでおきましょう!:16進数と10進数の変換は9まで一緒だしA以降は頑張ってください。Aが10、Cが12、Fが15とこれだけでも覚えておくと楽です。2進数と10進数の変換は、2進数の桁が何を表すかを知っておくと簡単です。下から1桁目は1、2桁目は2、3桁目は4、4桁目は8です。つまり1001だと8+1=9、1100なら8+4=12、0111なら4+2+1=7といった感じです。2進数と16進数の変換は、9までは10進数と同じです。A以降は形で覚えておくと楽です。交互に1010だったらA、それに1足された1011ならB。上2つが1の1100だったらC、それに1足された1101ならD。上3つが1の1110だったらE、全部1ならF。と言った具合です。
*7:8進数:0〜7までの8個の数字を使った表現。2進数の3桁を表すことができるため、16進数と同様に2進数との相性が良い。使った覚えはない。