##誤差が生じる理由
コンピュータは32ビット、64ビット等の範囲で様々な数を処理するわけですが、中にはその範囲を超えるような数があります。
たとえば、10進数の「$0.1$」を2進数に基数変換しようとすると、
0.000110011001100110011001...
というように、数が無限に続いてしまいます。
もし、この数を限られたビット数の浮動小数点数に表現するとしたら、やはり無理なわけです。
したがって、コンピュータがこのような数を扱う際には**「極力それに近い値」**で済ませるしかありません。
こうして、実際の2進数と「極力それに近い値」との間で誤差が生じることになります。
この例では10進数の基数変換を取り上げましたが、コンピュータが数を処理する際には他にも様々な誤差が生じます。
##桁あふれ誤差
演算した結果、コンピュータが表現できる最大値や最小値を超えてしまうことによって生じる誤差が桁あふれ誤差です。
ここでは例として、2進数を下の図のような32ビット形式の浮動小数点数にする場合について取り上げます。
この形式において指数部に着目すると、この部分は7ビットで2進数を2の補数を使って表現しています。これはつまり、「左から1ビットを符号ビット、残り6ビットを整数とした固定小数点数」と同じ形になっていることが分かります。
下の表はこの固定小数点数の各桁の構造と最大値・最小値をまとめたものです。
| 桁数 | 符号ビット | 6 | 5 | 4 | 3 | 2 | 1 |.| 10進数 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| | | | | | | | | | |
|(最小値)| 1 | 0 | 0 | 0 | 0 | 0 | 0 | | -64 |
| | 1 | 0 | 0 | 0 | 0 | 0 | 1 | | -63 |
| | … | … | … | … | … | … | … | | … |
| | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 |
| | … | … | … | … | … | … | … | | … |
| | 0 | 1 | 1 | 1 | 1 | 1 | 0 | |62|
|(最大値)| 0 | 1 | 1 | 1 | 1 | 1 | 1 | |63|
この表から、固定小数点数、つまり「7ビットで2進数を2の補数を使って表現した指数部」が表すことができる範囲は、10進数で「$-64$〜$63$」であることが分かります。
指数で表現できる範囲 (7ビット) | |
---|---|
最小値 | $-64$ ( $-2^{(7-1)}$ ) |
最大値 | $63$ ( $2^{(7-1)}-1$ ) |
範囲 | $-64$ 〜 $63$ |
この条件において、たとえば 「$0.11\times2^{100}$」という極めて大きな数を扱おうとした場合、指数の値「$100$」は指数部に入る最大値を超えてしまい収まりません。
同様に、「$0.11\times-2^{100}$」という極めて小さな数を扱おうとした場合も、指数の値「$100$」は指数部の最大値を超えてしまい、範囲に収まりません。
このように、表現可能な2進数の指数部が大きすぎて表現できないことをオーバーフローと呼びます。
オーバーフローは「$0.11\times2^{100}$」と「$0.11\times-2^{100}$」のように2進数の正と負の2つの場所で生じます。
したがって、オーバーフローをさらに詳しく分けるならば、「$0.11\times2^{100}$」のような正のオーバーフローと「$0.11\times-2^{100}$」のような負のオーバーフローに分けることができます。
これはつまり、正または負の方向に限らず、表現しようとする2進数の絶対値が大きすぎることによって生じると言い換えることもできます。
それでは逆に、2進数の絶対値が小さすぎる場合について考えてみたいと思います。
例として、「$0.11\times2^{-100}$」や、「$0.11\times-2^{-100}$」のような指数の絶対値が極めて小さな値について取り上げてみます。
この場合、先ほどの図を踏まえるならば、最大値と最小値の範囲には収まっているため、一見問題無いように思われます。
ところが、実際にこの2つの数の指数を指数部に格納しようとすると、指数の値「$-100$」は指数部の最小値を超えてしまい、範囲に収まりません。
このように、表現可能な2進数の指数部が小さすぎて表現できないことをアンダーフローと呼びます。アンダーフローは「$0.11\times2^{-100}$」と「$0.11\times-2^{-100}$」のように正と負の2つの場所で生じます。
したがって、アンダーフローをさらに詳しく分けるならば、「$0.11\times2^{-100}$」のような正のアンダーフローと「$0.11\times-2^{-100}$」のような負のアンダーフローに分けることができます。
これらを踏まえて、オーバーフローとアンダーフローについて整理したものが以下の図になります。
浮動小数点数では非常に小さな数から大きな数まで表現することが可能な便利な表現方法です。しかし、オーバーフローやアンダーフローなどの限界が存在し、これが原因で誤差が生じてしまうこともあるということが分かりました。
##参考にさせて頂いた書籍
きたみりゅうじ 『キタミ式イラストIT塾 基本情報技術者平成31/01年』 技術評論社 2019年
##学習してみて
今回から「誤差」についての学習に取り掛かりました。
オーバーフローとアンダーフロー。今までで一番難しかったです。
特にアンダーフローについて勉強していると、「絶対値が」大きいということと「正の方向に」大きいということが混同されてしまって、分かったつもりになっては「あれ、おかしいな」と気付くことの繰り返しでした。
前回で浮動小数点数がとても便利な表現方法であるということが分かったわけですが、やはりそれでも限界はあったということですね。