情報ラボ > 数の表し方と計算の誤差
コンピュータは、決まった数のビットで数を表します。だから、表せない数や、ずれてしまう計算があります。ビットを動かして確かめましょう。
左はしのビット(赤い枠)は、2の補数では「符号ビット」になります。1なら負の数です。
コンピュータの中では、数はすべて0と1の並び(ビット)で表されます。紙に書く計算なら、桁が足りなくなれば書き足せますが、コンピュータはあらかじめ決めたビット数で数を記録します。8ビットなら 28 = 256 通り、32ビットなら約43億通りの並びしかありません。そのため、表せる数には範囲があり、また小数の多くは正確には表せません。これが、コンピュータの計算に誤差が生まれる理由です。
負の数を表す方法として、多くのコンピュータで使われているのが2の補数です。8ビットの場合、左はしのビットを「−128 の位」とみなして読みます。たとえば 11111010 は、−128+64+32+16+8+2 = −6 です。左はしのビットが1なら負の数、0なら0以上の数になるので、このビットを符号ビットといいます。8ビットの2の補数で表せるのは −128 から 127 までです。
ある数の符号を反転する(−をつける)には、「すべてのビットの0と1を入れかえて、1を足す」という手順を使います。6(00000110)なら、入れかえて 11111001、1を足して 11111010(−6)です。
2の補数のよいところは、引き算を足し算で計算できることです。100 − 30 は、100 +(−30)として、ふつうの2進数の足し算の回路でそのまま計算できます。左はしからあふれたくり上がりを捨てれば、正しい答えになります。足し算の回路だけで引き算もできるので、回路を単純にできます。論理回路で、足し算をする回路のしくみも確かめてみましょう。
小数は、10進数の「6.02 × 1023」のような指数を使った書き方を、2進数で行って表します。この表し方を浮動小数点数といいます。多くのコンピュータは、IEEE 754 という国際的な規格に従っています。
| 形式 | 全体 | 符号部 | 指数部 | 仮数部 |
|---|---|---|---|---|
| 単精度 | 32ビット | 1ビット | 8ビット | 23ビット |
| 倍精度 | 64ビット | 1ビット | 11ビット | 52ビット |
たとえば −6.25 は、2進数で −110.01、これを「−1.1001 × 22」と書き直して記録します。仮数部の先頭の「1.」はいつも同じなので記録せず、そのぶん1ビット多く精度を持たせています。
10進数の 0.1 を2進数にすると、0.000110011001100…と「0011」が永遠にくり返す小数になります。仮数部のビット数は決まっているので、どこかで丸めるしかなく、記録される値は 0.1 からわずかにずれます。単精度では 0.100000001490116…、倍精度でも 0.1000000000000000055511…になります。一方、0.5 や 0.75 のように、2のべき乗の分数(1/2、1/4、1/8…)の和で表せる数は、ぴったり記録できます。
決まった桁数に入りきらない部分を、四捨五入などで丸めるときに生まれる誤差です。1回ごとのずれは小さくても、計算をくり返すとたまっていきます。単精度で 0.1 を1000回足すと、100 にはならず、99.99905 になります。
計算の結果が、表せる範囲をこえてしまうことです。8ビットの0以上の数では 255 + 1 が 0 に、8ビットの2の補数では 127 + 1 が −128 になってしまいます。ゲームの得点や、日付・時刻の計算などで問題になることがあります。
大きな数に、とても小さな数を足したとき、小さな数が結果に反映されずに消えてしまうことです。単精度の有効な桁はおよそ7けたなので、1億に1を足しても1億のままになります。たくさんの数を足すときは、小さい数から順に足すと、情報落ちを減らせます。
ほとんど同じ大きさの数どうしを引き算したとき、上の同じ桁が打ち消し合って、信頼できる桁が少なくなってしまうことです。√(x+1) − √x のような計算では、式を 1 ÷ (√(x+1) + √x) に変形すると、引き算をせずに計算できるので、桁落ちを防げます。
1991年2月25日、サウジアラビアのダーランで、迎撃ミサイルのシステムが飛来したミサイルの迎撃に失敗し、兵舎にいた28人のアメリカ兵が亡くなりました。アメリカ会計検査院(GAO)の報告によると、システムは時刻を24ビットのレジスタで実数に変換する際に精度を失っており、100時間以上連続で動かしたことで、そのずれがたまって約0.34秒になっていました。このずれのため、レーダーが目標を探す範囲が約687メートルずれていたとされています。小さな誤差でも、くり返しによって大きな影響を生むことがあるのです。