#12 基数(2進数, 16進数など)

基数とは

私たちは普段基数10で数を数えています。 これを10進数 (decimal) と言います。

10進数は0, 1, 2, 3と数えていって、10になったときに桁がひとつ増えます。

これは

のふたつの見方があります。

同じように2桁目も10になったとき3桁に増えますし、2桁目も10種類の数があります。

しかし場合によっては異なる物の数え方をしたほうが便利な場合もあります。 多くは物理的特性、あるいは構造が10進数と異なる法則になっており、10進数で数えると半端な数になってしまう場合です。

特にコンピュータは2つの状態を持つため、ONとOFFの2状態表現によってコンピュータの実際の状態と一致させることができます。 これを0と1という数値に置き換えれば計算ができるようになります。

しかし、このような2値状態を表現すると10進数ではキリのいい数になりません。 そのため、これをそのまま表現する2進数、わかりやすく表現できる16進数、そして歴史的経緯から使われている8進数が使われます。

基数10以外の数を基数10に直す方法

基数10より少ない数として8進数を取り扱いましょう。 8進数は0から7までの8種類の数を使い、7の次は桁がひとつ増えて10になります。

例えば次の8進数

755

これを10進数に直すといくつになるのでしょうか?

まず1桁目はそのままです。 考え方としてはこの桁が表す数に1をかけます。

5 * 1 == 5

2桁目以降は基数に桁数から1を引いた数の累乗をかけます。

5 * 8^1 == 40

この場合8の1乗なので8、5かける8なので40です。

次の桁は7です。3桁目なのでこれに8の2乗(64)をかけます。

7 * 8^2 == 448

こうして各桁の数を算出し、足し合わせます

5 * 1 + 5 * 8^1 + 7 * 8^2
5 * 1 + 5 * 8 + 7 * 64
5 + 40 + 448
= 453

2進数 (digit, binary)

2進数は2つの状態を持つ電子チップに合わせて、 ON状態を1、OFF状態を0として表したものです。

例えば4つのセルが

ON - OFF - OFF - ON

であるとき、

1001

となります。

また、曖昧な状態を持つものであっても2つの状態に振り分けることでエラーを極めて少なくすることができます。

コンピュータはこの2値状態に従って計算を行います。

0と1しかないため、1の次には桁が上がります。

0
1
10
11
100
101
110
111
1000
1001
1010
1011
1100
1101
1110
1111

2進数の1桁(単一のON/OFF状態)を1ビットといいます。 また、2進数は8桁ひと組で使うことが多く、8桁をバイトと言います。

2進数は通常、桁数は決まっていて実際は桁上がりをしません。 予め確保されているより大きな桁は0で埋められています。

00010110 + 01100111 = 01111101

2進数は非常によく使うこと、2進数の累乗は数が小さく比較的計算しやすいことから、 よく使う桁の数は覚えることが一般的です。

2進数の数 10進数の数
0 0
10 2 (2^1)
100 4 (2^2)
1000 8 (2^3)
10000 16 (2^4)
100000 32 (2^5)
1000000 64 (2^6)
10000000 128 (2^7)
100000000 256 (2^8)
1000000000 512 (2^9)
10000000000 1024 (2^10)
100000000000 2048 (2^11)
1000000000000 4096 (2^12)
10000000000000 8192 (2^13)
100000000000000 16384 (2^14)
1000000000000000 32768 (2^15)
10000000000000000 65536 (2^16)
1000000000000000000000000 16777216 (2^24) (約1677万)
100000000000000000000000000000000 4294967296 (2^32) (約42億)
10000000000000000000000000000000000000000000000000000000000000000 18446744073709551616 (2^64) (約1844京)

単に数字を提示したときに基数2がわかるように、0bをつけて表現する場合もあります。

0b10011100

16進数 (hexdecimal)

16進数はひと桁あたり16の数を持ちます。

16である理由は2^4に等しく、2桁で2^8、つまり1バイト分(2進数の8桁)を表すことができるからです。

とはいえ数字が16もないため、10からはAではじまりB, C, DとカウントしてFまであります。

Fは10進数にすると15で、その次は10になります。

基本的に16進数は1バイトを表すために2桁ひと組で使われるため、2桁までしか使われません。 より大きい数を表す場合でも2桁ごとで区切ります。

2桁で最も大きいFFは10進数に直すと255です。

単なる数を16進数であることを示すために0xをつけて表現する場合もあります。

また、このxと数を混同しないために通常数は大文字で表現されます。

文字と16進数

現在文字はUnicode上の番号(これも16進数)で言うことが増えていますが、ASCIIコード上の特別な文字に対して区別がつきやすいように名前ではなく16進数で表現する場合があります。

特に仕様されるのはバックスラッシュを表す0x5Cと、スペースを表す0x20です。

バックスラッシュは各国の文字集合で別の文字が当てられているため名前で通じないことがあります。 実際、日本語文字集合では円マークが当てられています。

そこで文字としてのバックスラッシュを表すために0x5cという呼び方を使用します。

また、Unicode上ではバックスラッシュにU+005Cが、円マークにはU+00A5が当てられています。 ですから、これらは現代では区別可能なはずですが、伝統的に日本語フォントが0x5Cとして円マークを使用してきたこと、 キーボードから直接U+00A5が打てないことから依然として日本語フォントはU+005Cとして円マークを使用していることが一般的です。

このような混同を避けるために0x5Cという呼び方をします。

0x20はスペースキーで入力できる普通の半角スペースです。 スペース文字は色々あり、呼び方も複雑なので、明確にこのスペース文字を表すために0x20を使用します。

8進数 (Octal)

8進数を使うことで2進数の3桁を表すことができます。

かつては2進数6桁をひと組として使う(1ワード6ビット、現在の1バイトのようなの)ことが多かったため、 バイトと同じような感覚で使われました。

現在8進数を使うケースはごく稀ですが、ファイル管理のパーミッションなど一部フラグ管理に8進数を使うものがあります。 これは「フラグが3種類ある」ものに対して適当なためです。

数値が8進数であることがわかるよう、0を頭につけたりします。

文字と文字列

さて、ここで文字と文字列の違いのお話をします。

なぜそんなに文字列を文字と区別するのか?

ひとつは文字というのが異なる概念を指すから、ということがあります。 先程のU+005Cのような話です。

しかし、それ以上に「ASCII文字は127までの数に1文字ずつ割り当てている」というのが大きな理由です。

ASCIIは127までなので7ビットです。 現在は1characterというと一般的には1バイトと等しく8ビットですが、 以前は1characterというと7ビットでした。

そして、「文字」は7ビットで表せる数そのものなのです。

RubyやPerlでは「文字列文字列」として扱おうとします。 文字を数値として扱うことは好みません。

けれど、そのようなことを望むのなら、そのようなことをすることも可能です。

65

"A"という文字列から65という数値を得ることができました。 また、逆に数値からそれにあたる文字列を得ることもできます。

F

C言語などではchar型は完全な数値型です。

このことから明確に文字列と文字は別物、と考える必要があります。 

Fullsized Image