1-1基数と2進数
水曜の夕方、通販の注文を確かめていたミナトは、送料の欄で手を止めました。1袋0.1kgのラスクを3袋頼んだお客さんに、「0.3kgまで」のポスト投函便ではなく、一つ上の宅配便の送料がかかっています。合計の重さの欄には「0.30000000000000004kg」と出ていました。横からのぞき込んだ店長は目を丸くします。「0.1を3回足しただけだよ。コンピュータでも計算を間違えるのかい」。ミナトにも理由が分かりません。画面の数字を相棒に打ち込むと、こう返ってきました。「間違えたというより、0.1をぴったり持てないんだと思う。コンピュータが数をどう持っているかから、順にたどってみよう」
ふだん使っている数は、0から9までの10種類の数字を並べて書きます。365なら、3は百の位、6は十の位、5は一の位にあり、3×100+6×10+5×1という意味です。位が一つ左へ進むごとに、重みは10倍になります。この「何倍ずつ重みが増えるか」を決める数を基数といい、基数が10の表し方が10進数です。
コンピュータの中では、電圧が高いか低いかのような2つの状態で情報を扱います。そこで、0と1の2種類の数字だけで数を表す2進数(バイナリ)を使います。基数は2なので、位の重みは右から1、2、4、8、16…と2倍ずつ増えます。2進数の1101は、8×1+4×1+2×0+1×1で、10進数の13です。
反対に10進数を2進数に直すときは、2で割って余りを書き留めることをくり返します。13÷2は6余り1、6÷2は3余り0、3÷2は1余り1、1÷2は0余り1です。余りを最後のものから順に並べた1101が答えになります。ある基数の表し方から別の基数の表し方へ直すことを基数変換と呼びます。基数をnとして広げた表し方はn進数といい、どのnでも、位の重みはn倍ずつ増えていきます。
2進数は、すぐに桁が長くなります。10進数の200は、2進数では11001000の8桁です。そこで、2進数を右から4桁ずつ区切り、1桁で0〜15を表す16進数に直して書くことがよくあります。10〜15にはA〜Fの文字を使うので、11001000は1100と1000に分けてC8です。3桁ずつ区切れば、0〜7の数字で表す8進数になり、011・001・000で310と書きます。どちらも、2進数と行き来しやすいところが便利です。
2進数の1桁をビットと呼び、コンピュータは決まったビット数で数を持ちます。8ビットなら00000000から11111111まで、10進数の0から255までの256個の数を表せます。足し算は10進数と同じ筆算で、1+1が2になったら0を書いて上の位へ1を繰り上げます。0101(5)+0011(3)は、下の3つの位で繰り上がりが続いて1000(8)です。引き算も、足りない位では上の位から借りてきて計算します。
ここから基本情報!nビットで区別できる数
nビットの並びが取りうる、0と1の組み合わせの一つ一つをビットパターンといいます。1ビット増えるごとに組み合わせは2倍になるので、nビットのビットパターンは2のn乗通りです。こむぎ堂の商品40種類に別々の番号を振るとしましょう。5ビットでは32通りで足りず、6ビットなら64通りで足ります。「2のn乗が、区別したい数以上になる最小のn」を探せば、要るビット数が分かります。
基本情報の範囲ここまで
小数も、同じ考え方で表せます。2進数で小数点より右の位の重みは、1/2、1/4、1/8…と半分ずつ小さくなります。10進数の小数を2進数に直すには、2を掛けて整数の部分を取り出すことをくり返します。0.625なら、0.625×2=1.25で1、0.25×2=0.5で0、0.5×2=1.0で1。小数の部分が0になったところで終わり、0.101が答えです(1/2+1/8=0.625)。
同じ手順を0.1で試すと、終わりが来ません。0.1×2=0.2で0、0.4で0、0.8で0、1.6で1、残りの0.6×2=1.2で1、そして0.2に戻ります。あとは0.2→0.4→0.8→0.6がいつまでも巡り、0.000110011…と「0011」がくり返されます。10進数で1/3が0.333…と終わらないのと同じで、0.1は2進数では割り切れない数なのです。コンピュータは限られたビット数で打ち切って持つので、0.1kgはほんのわずかにずれた値になります。それを3回足すとずれが積み重なり、0.30000000000000004kgとして表に出ました。
ここから基本情報!16進数の小数
16進数で小数を表したものが16進小数です。小数点より右の位の重みは、1/16、1/256…と16分の1ずつ小さくなります。2進数の小数は、小数点から右へ4桁ずつ区切れば、そのまま16進小数に直せます。2進数の0.101は0.1010と見てA、つまり16進小数の0.Aで、10/16=0.625です。10進数の0.1は、2進数で0.0001 1001 1001…なので、16進小数では0.1999…と9が並び、やはり終わりません。
基本情報の範囲ここまで
1-2数値の表現
金曜の閉店後、ミナトは在庫の記録を見直していました。焼き上がった数を足し、売れた数と取り置きの数を引いていくと、予約が重なった日には在庫が「−2個」になります。0と1しか使えないコンピュータは、この「−」をどこに書いているのでしょうか。0.1kgの「.」も、同じ疑問を残したままです。
紙なら、数の前に「−」を、途中に「.」を書けば済みます。コンピュータには0と1しかないので、負の数も小数点の位置も、ビットの並べ方の決まりとして表します。どの決まりを選ぶかで、同じビット数で表せる数の範囲や細かさが変わります。
ここから基本情報!負の数の表し方
負の数の表し方として広く使われているのが、補数を使う方法です。中でも2の補数は、ある数の各ビットを反転(0と1を入れ替え)してから1を足して作ります。8ビットで5は00000101なので、反転すると11111010、1を足した11111011が−5です。この表し方では最上位のビットが1なら負の数、0なら0以上の数と読めます。
2の補数を使うと、引き算を足し算で済ませられます。12−5は12+(−5)と考えて、00001100+11111011を計算します。結果は100000111と9桁になりますが、8ビットからあふれた最上位の1を捨てると00000111、つまり7です。引き算のための回路を別に用意しなくてよいのが利点です。8ビットの2の補数で表せる範囲は、−128から127までです。
基本情報の範囲ここまで
小数を含む数では、小数点をどこに置くかが問題になります。在庫の個数のような整数なら、2進数でぴったり表せます。ところが重さや温度のような値は、0.1のように2進数で割り切れない数を含み、大きさもさまざまです。
ここから基本情報!固定小数点数と浮動小数点数
小数点の位置をあらかじめ決めた桁に固定して表す方式が固定小数点数です。たとえば16ビットのうち下の8ビットを小数の部分と決めれば、1/256刻みの数を表せます。仕組みは単純ですが、とても大きな数ととても小さな数を、同じ形で持つのは苦手です。
そこで、数を「仮数×2の指数乗」の形に分けて持つ浮動小数点数が使われます。10進数で1230を1.23×103と書くのと同じ考え方です。1.23のように有効数字の並びを表す部分を仮数、103の3のように小数点を何桁動かすかを表す部分を指数といいます。指数を変えれば小数点が動くので、広い範囲の数を同じビット数で表せます。
形式は、IEEE(米国に本部を置く電気・電子技術の学会)が定めたIEEE 754という規格で決められています。同じ内容は、国際規格のISO/IEC 60559にもなっています。符号1ビット・指数部8ビット・仮数部23ビットの計32ビットで表すのが単精度浮動小数点数(単精度)です。符号1ビット・指数部11ビット・仮数部52ビットの計64ビットで表すのが倍精度浮動小数点数(倍精度)です。10進数に直すと、単精度はおよそ7桁、倍精度はおよそ15〜16桁の精度になります。倍精度は精度が高いぶん、1つの数に2倍の記憶領域を使います。
| 形式 | 全体 | 符号 | 指数部 | 仮数部 | 10進数でのおよその精度 |
|---|---|---|---|---|---|
| 単精度 | 32ビット | 1ビット | 8ビット | 23ビット | 7桁 |
| 倍精度 | 64ビット | 1ビット | 11ビット | 52ビット | 15〜16桁 |
どちらの形式も、仮数を「1.○○…」の形にそろえ、先頭の1は書かずに省きます。−6.5で試すと、2進数では−110.1、つまり−1.101×22です。単精度なら、符号ビットは1、指数部には2に127を足した129(10000001)、仮数部には先頭の1を除いた101のあとに0を並べたものが入ります。指数部に一定の値を足しておくのは、負の指数も0以上の数として持てるようにするためです。冒頭の0.1は倍精度でも有限のビットに収まらず、0.1よりわずかに大きい値として持たれていました。
基本情報の範囲ここまで
一方、お金の計算のように、1円の狂いも許されない場面もあります。そうした場面では、10進数の桁をそのまま保って0と1で持つ方法も使われます。
ここから基本情報!10進数の桁のまま持つ方式
10進数の1桁を4ビットの2進数で表す方式をBCD(2進化10進数)といいます。365なら、3・6・5をそれぞれ0011・0110・0101に置き換えます。4ビットは0〜15を表せますが、BCDでは0〜9の10通りしか使いません。そのかわり10進数の桁がそのまま残るので、0.1が割り切れずにずれる、ということが起きません。
BCDを記憶装置に置く形式には、2つの決まりがあります。パック10進数は、1バイト(8ビット)に2桁ずつ詰め、最後の4ビットに符号を入れます。符号は正をC(1100)、負をD(1101)とする決まりが広く使われていて、+365は「36」「5C」の2バイトになります。ゾーン10進数(ゾーン形式)は、1バイトに1桁を入れ、上位の4ビット(ゾーン部)を決まった値で埋めます。符号は最後のバイトのゾーン部に入れるので、ゾーン部をFで埋める決まりなら、+365は「F3」「F6」「C5」の3バイトです。
基本情報の範囲ここまで
1-3算術演算と精度
月末、ミナトは店のポイントカードの記録を調べていました。いちばんの常連さんのポイントが、255から1つ増えたところで0に戻っています。古い集計の仕組みが、ポイントを8ビットで持っていたのです。「よりによって、一番のお得意さんじゃないか」と店長は頭を抱えました。
8ビットで表せる最大の数は11111111、つまり255です。これに1を足すと100000000の9桁になり、8ビットに入りきらない最上位の1が消えて、残るのは00000000、つまり0です。このように、計算の結果が表せる最大の値を超えてしまい、正しく表せなくなることをオーバーフロー(あふれ)といいます。コンピュータは、桁があふれても計算を止めずに結果を返すことがあるので、入りうる最大の値を見積もってビット数を決めておくことが対策になります。
ポイントの付け方にも、計算の決まりが隠れています。こむぎ堂では、100円ごとに1ポイントを付けます。1,380円の買い物なら1380÷100は13余り80で、付くのは13ポイントです。割り算で割り切れずに残る数(ここでは80)を剰余(余り)といいます。表計算ソフトではMOD関数で求められ、注文番号を3で割った余りで3人の係に振り分ける、といった使い方もできます。
同じ計算を13.8ポイントと見れば、小数の部分を捨てて13にしたことになります。指定した桁より下の数を、大きさに関係なく取り除く処理を切り捨てといいます。四捨五入なら14、切り上げなら14になるので、どの処理を選ぶかで結果が変わります。表計算ソフトでは、ROUNDDOWN関数で桁を指定して切り捨てられます。
あふれは桁の上限で起きる問題でした。コンピュータの計算で起きるずれには、桁の下限や有効数字の桁数に関わるものもあります。冒頭の0.30000000000000004kgも、限られたビット数で数を持つことから生まれたずれの一つです。
ここから基本情報!シフト演算
2進数では、ビットの並びを左右にずらすだけで、2倍や1/2倍の計算ができます。10進数で末尾に0を付けると10倍になるのと同じです。符号を考えずに全部のビットをずらし、空いた桁を0で埋めるのが論理シフトです。00000110(6)を左へ1ビットずらすと00001100(12)、右へ1ビットずらすと00000011(3)になります。
負の数を2の補数で持っているときは、論理シフトでは困ります。−8(11111000)を右へ1ビット論理シフトすると01111100となり、符号が変わって124になってしまいます。そこで、符号ビットを残したままずらすのが算術シフトです。右へずらすときは、空いた左端を符号ビットと同じ値で埋めます。−8を右へ1ビット算術シフトすると11111100で、ちょうど半分の−4です。左へ算術シフトするときは、符号ビットを除いた部分をずらし、空いた右端を0で埋めます。
符号付きの数でも、あふれは起きます。8ビットの2の補数で100+50を計算すると、結果の150は表せる最大の127を超えます。ビットの並びは10010110となり、最上位が1なので、−106と読めてしまいます。
基本情報の範囲ここまで
ここから基本情報!浮動小数点数の計算で起きる誤差
あふれと反対に、計算の結果の絶対値が0に近すぎて、浮動小数点数で表せる最小の大きさより小さくなることをアンダーフローといいます。とても小さな値どうしを掛け合わせたときなどに起き、結果は0になったり、精度の落ちた値になったりします。
値がほとんど等しい2つの数を引き算すると、有効数字の桁数が大きく減ります。これを桁落ち(けた落ち)といいます。有効数字7桁の1.234567から1.234566を引くと、答えは0.000001で、有効数字は1桁しか残りません。上の桁どうしが打ち消し合ったためです。近い値の引き算を避けるように、式の形を変えて計算することが対策になります。
絶対値の大きな数と小さな数を足したり引いたりすると、小さい数が結果に反映されないことがあります。これが情報落ちです。有効数字4桁で1234+0.1を計算すると、正しくは1234.1ですが、4桁に収めると1234に戻り、0.1は消えてしまいます。小さな数をたくさん足すときは、小さい数どうしを先に足してから大きな数に足すと、情報落ちを減らせます。
基本情報の範囲ここまで
1-4集合と命題
秋の新作の案内を、常連さんにメールで送ることになりました。店長の注文は「ライ麦パンを買ったことがある人と、くるみパンを買ったことがある人に送って。同じ人に2通は送らないでね」。購入の記録から名前を書き出していくと、両方の一覧に出てくる人が何人もいます。ミナトは、送る人数を数え直すことになりました。
「ライ麦パンを買ったことがある人」のように、入るか入らないかがはっきり決まるものの集まりを集合といいます。一方、「パンが好きな人」は、好きかどうかの判断が人によって分かれるので、そのままでは集合として扱えません。集合に入っている一つ一つのもの(ここでは一人ひとりのお客さん)を、要素と呼びます。
集合どうしの関係は、円を重ねた図にすると見通しがよくなります。全体を四角で囲み、その中に集合を円で描いた図がベン図です。ライ麦パンを買った人の円と、くるみパンを買った人の円を描くと、両方を買った人は2つの円が重なる部分に入ります。ライ麦が30人、くるみが20人、両方が8人なら、送る相手は30+20−8=42人です。重なりの8人を2回数えないように引きます。
ここから基本情報!集合の演算
ライ麦パンを買った人の集合をA、くるみパンを買った人の集合をBとします。AとBのどちらか一方、または両方に入る要素全体の集合が和集合で、A∪Bと書きます。案内を送る42人がこれです。AとBの両方に入る要素全体の集合が積集合で、A∩Bと書き、重なりの8人にあたります。
考える範囲全体を全体集合といいます。常連さん150人を全体集合とすると、そのうちAに入らない120人の集合が、Aの補集合です。また、「ライ麦パンを毎週買う人」の集合Cの要素は、全員がAにも入っています。このように、ある集合の要素がすべて別の集合にも入っているとき、CはAの部分集合であるといい、C⊂Aと書きます。
基本情報の範囲ここまで
集合と同じように、正しいか正しくないかがはっきり決まる文を命題といいます。「この人はライ麦パンを買ったことがある」は、購入の記録を見れば決まるので命題です。「ライ麦パンはおいしい」は、人によって答えが分かれるので命題ではありません。ある人について「ライ麦パンを買った」という命題が正しいことと、その人がライ麦パンの集合に入っていることは、同じことを言っています。
ここから基本情報!真と偽、命題論理
命題が正しいことを真、正しくないことを偽といい、コンピュータでは真を1、偽を0で表すのがふつうです。真と偽をまとめて真理値と呼びます。命題を「かつ」「または」「でない」でつなぎ、つないだ全体が真か偽かを求める論理学の分野を命題論理といいます。「ライ麦パンを買った、かつ、くるみパンを買った」が真になる人は、積集合A∩Bの8人です。「かつ」は積集合に、「または」は和集合に、「でない」は補集合に対応します。
基本情報の範囲ここまで
1-5論理演算
通販サイトに、商品の絞り込みを付けることになりました。「ライ麦もくるみも入ったパンはありますか」「くるみが苦手なので、くるみなしのパンを」と、問い合わせが続いたからです。ミナトは条件の組み合わせ方を相棒と書き出していきます。「条件が成り立つなら1、成り立たないなら0と置くと、全部の組み合わせを表にできるよ」
条件Aを「ライ麦を含む」、条件Bを「くるみを含む」とし、成り立つときを1、成り立たないときを0とします。1か0かを入力にとり、1か0かを返す計算が論理演算です。基本になるのは4つあります。1と0を入れ替える否定(NOT)、AとBの両方が1のときだけ1になる論理積(AND)、少なくとも一方が1なら1になる論理和(OR)、そしてAとBが異なるときだけ1になる排他的論理和(XOR)です。
入力の組み合わせのすべてについて、出力を書き出した表を真理値表といいます。こむぎ堂の4つのパンで書くと、次のようになります。
| パン | A(ライ麦) | B(くるみ) | A AND B | A OR B | A XOR B | NOT B |
|---|---|---|---|---|---|---|
| 塩パン | 0 | 0 | 0 | 0 | 0 | 1 |
| くるみあんぱん | 0 | 1 | 0 | 1 | 1 | 0 |
| ライ麦食パン | 1 | 0 | 0 | 1 | 1 | 1 |
| ライ麦くるみブレッド | 1 | 1 | 1 | 1 | 0 | 0 |
「ライ麦もくるみも入ったパン」はA AND Bが1の行で、ライ麦くるみブレッドだけです。「くるみなしのパン」はNOT Bが1の行で、塩パンとライ麦食パンが出てきます。入力が2つなら、組み合わせは4行で必ず尽きます。条件が3つに増えると8行、4つなら16行と、1つ増えるごとに行は2倍になります。
ここから基本情報!論理関数と演算の法則
入力の真偽の組み合わせごとに、出力の真偽を1つ決める関数を論理関数といいます。どの論理関数も、真理値表で書き表せます。入力が2つなら真理値表は4行で、各行の出力を0か1に決めるので、2入力の論理関数は2の4乗の16通りあります。ANDやORは、その中の代表的なものです。
ANDの結果を反転させたものが否定論理積(NAND)で、両方の入力が1のときだけ0になります。ORの結果を反転させたものが否定論理和(NOR)で、両方の入力が0のときだけ1になります。上の4つのパンで見ると、NANDが0になるのはライ麦くるみブレッドだけ、NORが1になるのは塩パンだけです。
否定と、論理積・論理和の組み合わせには、決まった書き換え方があります。「ライ麦もくるみも入っていないパン」は、NOT (A OR B) とも、(NOT A) AND (NOT B) とも書けて、どちらも塩パンを指します。同じように、NOT (A AND B) は (NOT A) OR (NOT B) と等しくなります。論理和の否定は否定の論理積に、論理積の否定は否定の論理和に書き換えられる、という決まりがド・モルガンの法則です。
もう一つ、かっこを開くときの決まりがあります。条件Cを「チーズを含む」とすると、A AND (B OR C)(ライ麦を含み、くるみかチーズを含む)は、(A AND B) OR (A AND C) と同じ結果になります。数の計算のa×(b+c)=a×b+a×cと同じ形で展開できる、という法則が分配則です。論理演算では、A OR (B AND C)=(A OR B) AND (A OR C) と、ANDとORを入れ替えた形も成り立ちます。
基本情報の範囲ここまで
論理演算は、条件で探すためだけのものではありません。0と1の計算なので、2進数の足し算そのものも、論理演算の組み合わせで作れます。
ここから基本情報!論理演算で足し算を作る
1桁の2進数AとBを足すと、0+0=0、0+1=1、1+0=1、1+1=10です。結果の一の位(和)は、AとBが異なるときだけ1なのでA XOR B、上の位への繰り上がりは、両方が1のときだけ1なのでA AND Bです。この2つの出力を返す回路を半加算器といいます。半加算器は下の位からの繰り上がりを受け取らないので、何桁もの足し算をするには、繰り上がりの入力も持つ回路(全加算器)を組み合わせます。
基本情報の範囲ここまで
翌週、ミナトは通販の仕組みを直しました。重さを「0.1kg」という小数ではなく、「100g」という整数で持つようにしたのです。ラスク3袋は100+100+100=300gで、「300gまで」のポスト投函便にきちんと収まりました。整数なら、2進数でもぴったり表せます。送料の画面を見た店長は、ほっとした顔で言いました。「コンピュータが間違えたわけじゃなかったんだね。持ち方を選べばよかったんだ」
0.1が2進数で割り切れないことは、どの形式を選んでも変わりません。変えられるのは、どの単位で、何ビットで、どの決まりで数を持つかです。送料の区分のように境目ちょうどの値が結果を分ける計算では、小数のまま比べず、整数に直してから比べると、こうしたずれを避けられます。