基数

n進数

n進数で表された数について,nを基数と言い,n進数で表された数Xを(X)n等と表します.まず,桁と基数の関係について,具体的な数を用いて説明します.

(12.34)10は,101×1+100×2+10-1×3+10-2×4と表せます.一方,(56.78)16は,161×5+160×6+16-1×7+16-2×8と表せます.一般的に,n進数で表された数を10進数で考えると,整数部分の下a桁目はna-1,小数点以下b桁目はn-bです(a,bは正の整数).

Point

基数をp,表す数をNとおくと,表示に必要な桁数はlogpNです.

基数を大きくすると,表示に必要な桁数は少なくなりますが,表示に使う文字は多くなります.一方,基数が小さくなると,表示に使う文字は少なくなりますが,桁数は多くなります.証明は省略しますが,2つのバランスが一番良いのはe進法(eは自然対数の底)です.

ただし,コンピュータは整数個の回路で設計するので,基数は整数でなければいけません.eに最も近い整数は3ですが,コンピュータの性質(機械はオンかオフで判断する)により,2進数が採用されています.

基数変換(基底変換)

10進数とn進数(n≠10)

ある基数で表された数を,別の基数の数に変換することを基数変換と言います.先の項目で,桁と基数の関係について説明しました.この関係を用いれば,n進数への変換ができます.逆に,10進数からn進数への変換も,べき乗の形にすることで変換ができます.

例えば,(5.625)10の整数部分は5=22+20,小数部分は0.625=2-1+2-3ですから,(5.625)10=(101.101)2です.ただし,日常生活では10進数を使っている私達にとって,この方法は少々手間がかかります.そこで,n進数への変換を機械的に行う方法を示します.先ほどの例は以下のように表現できます。

10進数の5.625を2進数へ変換する図

整数部分は変換したい基数で割っていき,最後が1になるまで続けます.そして,最後の数(必ず1です)を先頭にし,割り算で得られた余りを下から順にたどっていきます.一方,小数部分は変換したい基数でかけ算を行っていき,小数点以下が0になるまで続けます.そして,かけ算で整数となった部分の数字を順番に並べていきます.

なお,全ての10進数がn進数で正確に表現できるとは限りません.例えば,10進数の0.1は,いくら2をかけても小数点以下は0になりません.n進数から10進数に変換する場合も同じことが起こりえます.ただし,2進数や8進数等,2のべき乗である基数で有限小数の場合,10進数でも必ず有限小数で表せます.

n進数とn進数

多くは2進数・8進数・16進数間の相互変換です.2進数から16進数への変換は,先ほど示した図の方法を用いる必要はありません.例えば,(10100101)2を16進数に変換する場合,16=24ですから,4桁ずつ区切ったものを16進数に変換します.実際には,(1010)(0101)とし,それぞれのブロックを16進数に変換すると(C)(5)となるので,答えは(C5)16です.16進数から2進数への変換は,逆の操作になります.2進数から8進数への変換では,8=23ですから,3桁ずつ区切ります.

8進数と16進数の相互変換では,いったん2進数にしてから変換すると良いでしょう.

Topic

基数変換そのものを面白いと思う人は多くないと思いますが,これが分かっていないと大変なことになりかねません.

ある学校(ネットワーク系の2年制の学科)の学生が,卒業間際になってもネットワークの切り方(サブネットワークの作成)が分からないと言っていました.

最初,先生はネットワークの切り方自体が分かっていないと思っていたそうですが,いくら教えても理解できない様子です.もしや,IPアドレスの基数変換(2進数と10進数の相互変換)が分からないのではと想像し,試しに基数変換の問題を解かせてみたら,全くできなかったそうです.

この学科のカリキュラムでは基数変換を早い時期に学びます.この学生は努力して卒業できたようですが,卒業間際から入学直後の状態まで学習内容が戻ったことになります.

数値表現

四則演算

補数

コンピュータは演算回路を使って数値を計算します.ただし,足し算をする回路はありますが,引き算・かけ算・割り算をする回路はありません.引き算は補数を使って計算します.

一般に,n進法で表される数に対して,nの補数n-1の補数があります。nの補数は,k桁のある整数とそれを足すと,ちょうど(k+1)桁の数で表現する最小値になるものです.n-1の補数は,k桁のある整数とそれを足すと,ちょうどk桁の数で表現する最大値になるものです.よって,n-1の補数に1を足したものがnの補数です.

888の10の補数と9の補数を求めます(3桁なのでk=3).

補数を使うと引き算を足し算で求めることができます.例えば,10進数の1000-888という計算を考えます.888の10の補数は112ですから,1000-888を1000+112と置き換えます.1000+112=1112に対し,1000-888=112ですから答えは一致しません.しかし,1000+112=1112における最上位の位を無視すると112となり,1000-888の答えと一致します.

一般に,引く数のnの補数を,引かれる数に足し,結果の最上位の位を無視すると,元の引き算の答えを求められます.

2の補数を機械的に求める方法があります.(00101101)2を例にします.

ビットを反転(0を1に,1を0に)すると(11010010)2で,これは元の数の1の補数です.2の補数はそれに1を足したものなので,(11010010)2+(1)2=(11010011)2であり,これが求めるものです.

また,上位の桁から順にビットを反転し,最後に1がでてくる1つ前までそれを続けると求まります.例に挙げた数で,最後に1がでてくるのは下から1桁目です.よって,そこまでのビットを反転する(最後の桁は何もしない)と,(11010011)2となります.

かけ算・割り算はもう少し複雑です.かけ算は足し算,割り算は引き算の連続と見なせば計算できます.例えば,2×3は2+2+2と考えれば加算だけで計算できますが,この方法では計算に時間がかかります.次の項目では,この方法よりも高速に計算が行える,シフト演算について説明します.

シフト演算

2進数のビットを右や左に数ビット移動する演算です.例として,8ビットの(10110111)2を考えます.なお,符号部は上位1ビットとし,負数は2の補数で表すことにします.

算術シフト演算によって,かけ算や割り算を行えます.基本的に,左にnビットシフトすると2n右にnビットシフトとすると2-nになります.ただし,割り算の場合は,割られる数が割る数によって整数で割り切れないと正しい答えになりません.3÷2=1.5ですが,(3)10=(00000011)2であり,1ビット算術右シフトすると,(00000001)2=(1)10となってしまいます.

固定小数点数と浮動小数点数

実際に計算を行うなら,負数も扱う必要があります.また,科学技術計算では非常に大きい値や小さい値を扱いますが,これまでの表現方法では桁数が非常に多くなります.

そこで負数も含めた実数を扱うために,固定小数点数浮動小数点数があります.

固定小数点数

小数点の位置を固定して数値を表現します.長さはさまざまなものがありますが,8ビットの例を考えます.まず,符号を表す必要があるので,最上位のビットを符号部と,0は正数,1は負数とします.また,小数点の位置は最も右側とします(この場合は表される数が全て整数).

この仕様で+63を表すと次のようになります.

00111111

同じ仕様で-63を表す場合,3通りの方法が考えられます.

さて,どの方法で表示すれば良いでしょうか.ここで,0を表す場合を考えます.

絶対値表示では(00000000)2と(1000000)2の2通りの表し方ができます.また,1の補数表示でも(00000000)2と(11111111)2と,2通りの表し方ができます.しかし,2の補数では(00000000)2と一意に定まります.2の補数表示において,(10000000)2は-128、(11111111)2は-1を表すからです.

1つの数に対して複数の表現があると混乱を招くので,固定小数点数では負数は2の補数で表すことが一般的です.よって,nビットの固定小数点数で表すことのできる数値の範囲は-2n-1から2n-1-1までです.

浮動小数点数

固定小数点数では,負数を表す問題が解決されましたが,大きな数や小さな数に対する桁数の問題が解決されていません.浮動小数点数はm×Beという形式をとり,mを仮数部,Bを基数,eを指数部と言います.例えば,0.00031255は0.31255×10-3と表されます.

浮動小数点数の表現形式はコンピュータによって異なります.ここでは,パソコンやワークステーションで採用されているIEEEの表現方式を例に説明します.表現方法は以下の通りです(基数は2).なお,正や負の無限大等,特殊な数値については,ここでは考えません.

ビット数 1ビット 8ビット 23ビット
名称 符号部(s) 指数部(e) 仮数部(m)

小数点の位置は指数部と仮数部の間です.sは仮数が非負のとき0,負数のとき1とします.eは指数に127を足したもので,mは仮数から0.5を引いたものです.

eは8ビットなので28通りの表現ができますが,規格では-127から128を対応させています.ここで,127を足すと,表せる範囲が0から255となり,最小値の-127が0になります.すると,負数を表すために補数を使う必要がなくなり,表現が簡単になります.このように,実際の値に加算を行うことをバイアス(ゲタばき)と言います.

仮数部で,0.5を引く理由について,浮動小数点数の2進数における表現を考えます.例えば,(0.5)10=(0.1)2より,浮動小数点数で表すと(0.1)2×100です.しかし,同様に(0.01)2×101とも表せます.

同じ数に対する表現方法が複数あると,計算のときに混乱を招くので,IEEEでは,仮数が0.1XXX……という形になるよう操作します.そこから0.5を引くと0.0XXX……となり,小数点以下2桁以降の部分がそのまま仮数部になります.これらの操作を正規化と言います.

正規化のもう1つの目的は,表現できる数をなるべく多くすることです.仮数部が8桁なら,0.XXX……と調整してXXXの部分をそのまま仮数部にすれば8桁使えます.しかし,0.0XXX……とすると7桁しか使えません.桁数を多く使えることで,数値のデータの精度が上がります.

(例題)10進数0.375をIEEEの規格で表しなさい.

(0.375)10=(0.011)2より,(0.011)2×20だが,正規化して(0.11)2×2-1となる.符号部は正数なので0,指数部は-1+127=126より(01111110)2,仮数部は0.5を引くので(0.1)2となる.

00111111010000000000000000000000

なお,全体を32ビットで表現する形式を単精度,64ビットで表現する形式を倍精度と言います.

その他の数値表現

固定小数点数と浮動小数点数は2進数データという表し方で,数値全体を2進数で表しました.他の表し方として,数値を1桁ずつ2進数に対応させる10進数データがあります.代表的なものに2進化10進(BCD)コードゾーン10進数(アンパック10進数)パック10進数があります.一般に,2進数データは科学技術計算,10進数データは事務計算に使われます.

文字にはビットコードが割り当てられています.例として,EBCDICコードで文字がどのように表されているのかを説明します.

文字 EBCDICコード
011110000
111110001
211110010
311110011
411110100
511110101
611110110
711110111
811111000
911111001

コードの下4桁は数値を2進数表現したものです.これをもとにして,1桁を1バイトで表現するゾーン10進数,下位4ビットの部分のみを利用した,1桁を0.5バイトで表現するパック10進数に分けられます.なお,ゾーン10進数の上位4ビットをゾーン部,下位4ビットを数値部と言います.また,どちらの表現方法にも,符号を示す符号部があり,正数は1100,負数は1101です.

例として,+1234のそれぞれの表現を示します.

ゾーン10進数における+1234の表現
ゾーン部 数値部 ゾーン部 数値部 ゾーン部 数値部 符号部 数値部
1111 0001 1111 0010 1111 0011 1100 0100
パック10進数における+1234の表現
数値部 数値部 数値部 数値部 符号部
0000 0001 0010 0011 0100 1100

なお,ゾーン部はシステムの体系によって数値が異なります.

一般に,n桁の数値を表現するのに必要なバイト数は,ゾーン10進数がnバイト、パック10進数は(n+1)÷2バイト(小数点以下切り上げ)です.また,パック10進数で桁数が偶数の場合は,最初の4ビットに0が埋められます(そうしないと上の例では2.5バイトという半端な単位になります).

一方,2進化10進コードはn桁の数字を4nビットで表します.0から9までの値は2進法4桁で表せるからです.例えば,876は(8)10=(1000)2,(7)10=(0111)2,(6)10=(0110)2より,これらを順に並べて100001110110と表します.パック10進数の符号部は,このビット列(数字の0から9)と重複しないようになっています.

Column

「数字」と「数値」の区別について説明します.

180という数が社員番号を表すなら,大きさの概念は不要なため,「数字」です.しかし,身長の場合は,大きさの概念が必要なので「数値」となります.「数字」と「数値」の違いは大小の概念の有無です.数値の場合は,正負の概念も必要です.

演算精度

誤差と有効数字

数値Aの近似値をaのとき,a-Aを絶対誤差と言い,(a-A)÷Aを相対誤差と言います.また,誤差をeとすると,誤差の限界は|e|≦εとなるεの値です.このとき,a-ε≦A≦a+εが成立します.

数値Aと数値Bに対して,A+BとA-Bの有効桁数は,小数点の位置を合わせて計算した後,小数点以下の桁数の小さい方に合わせて四捨五入します.一方,A×BとA÷Bは,有効桁数の小さい方に合わせて四捨五入します.

誤差の種類

コンピュータの演算結果が,実際の計算結果と完全に等しいとは限りません.以下の誤差が発生する場合があります.

Point

科学技術計算でなくても,誤差が原因でプログラムが正常動作しないことがあります.例えば,0.5から0.1ずつ増やしていき,1.0になったときに,何らかの処理を実行するとします.しかし,正しくプログラムされていても,何も処理が実行されないことがあります.10進数の0.1を2進数で表現すると無限小数となり,打ち切り誤差が発生するからです.

また,三角関数の値を計算する場合,無限に続く円周率の値が問題となります.数学ではcos1[rad]=1ですが,コンピュータ上では微妙に値がずれることがあります.