『情報科学入門 Rubyを使って学ぶ』の練習問題の解答例の他、授業スライドの練習問題の解答例や、プログラミングのポイント等を掲載します。他クラスの方の利用歓迎。改良・訂正箇所ありましたらご指摘ください。

2011/01/30

[基]浮動小数点表現と誤差

ここでは二進法が扱われていますが、二進法と十進法の相互変換はできること前提で記述しています。


浮動小数点数
なんかめんどくさそーですけど、まあ実際面倒です。でも数学より簡単。
コンピュータは、すべてのデータをONとOFF、すなわち1と0で扱っています。二進法ってやつです。
で、大きな数を二進数で表すと、すっごい桁数がいる、っていうのはわかると思います。
そこで、なるべく少ない桁数で大きな数字を表現するために用いるのが、浮動小数点法。


たとえば、数字を表現するのに、32ビット与えられたとします。
普通の二進法で表現すると、最大値はたったの4,294,967,295(=2^32-1)。
しかし、浮動小数点数で表現すれば、なんと最大値は約3.4×10^38!なんというビットの節約。すばらしい。


浮動小数点表現にも何種類かありますが、現在、主に単精度(32ビット列で表す)と倍精度(64ビット列で表す)が使われています。
この二つは、ビット数がちょっと違うだけなので、ここでは単精度で説明していきます。


さて、単精度浮動小数点表現では、32ビットで数字を表しますが、まず、このビット列は3つの部分に分けられています。
それが、符号部s指数部d'1..d'c仮数部d1..dmです。
単精度では、それぞれ1桁、8桁、23桁となっています。
これが
  (-1)^s(2) × 1.d1d2...dm(2) × 2^( d'1d'2..d'c(2) - b )
というふうに数字を表現します。(2)は二進数ということです。
bバイアス値といい単精度では127です。


たとえば、次のような単精度浮動小数点数
1111111101100000000000000000000
を十進法表現になおすとどうなるのでしょうか。まず3つの部分にわけてみましょう。
1  11111110  11000000000000000000000
ということは、十進数では
   (-1)^1(2) × 1.11000000000000000000000(2) × 2^( 11111110(2) - 127 )
= (-1)^1 × { 2^0 + 2^(-1) + 2^(-2) } × 2^( 254 - 127)
= -1.75 × 2^127
≒ -2.977471 × 10^38
となります。


逆に、十進数で表された数、例えば
3145728
を単数度浮動小数点表現にしてみましょう。こちらの方が簡単だと思います。
素因数分解をすればいいだけだからです。
   3145728
= 2^20 × 3
= (-1)^0 × 1.5 × 2^21
= (-1)^0 × { 2^0 + 2^(-1) } × 2^( 148 -127 )
= (-1)^0(2) × 1.10000000000000000000000(2) × 2^( 10010100(2) - 127 )
ですね。というわけで、符号部、指数部、仮数部の順にならべて、
01001010010000000000000000000000
となります。
注意するのは、仮数部(1.d1..dm(2))は、1以上2未満の数字しか表現できないということ。


そして、以上の方法では0を表せないのがわかると思います。
なので、特別に、指数部と仮数部がともに全て0のときは0を表すことになっています。


因みに、倍精度浮動小数点表現では
指数部が11桁、仮数部が52桁、バイアス値は1023です。




誤差
浮動小数点数を用いた計算は、近似値による計算なので、誤差が生じます。
十進数では有限の桁数で表せるのに、二進数では無限に続く少数になってしまうような数が存在するからです。
たとえば0.1もそうです。
0.1 = 2^(-4) + 2^(-5) + 2^(-8) + 2^(-9)......
      = 0.0001100110011......(2)
      = 1.100110011......(2) × 2^(-4)
ね?
これで生まれてしまう誤差を丸め誤差と呼びます。


誤差には他に桁落ち誤差、情報落ち誤差、打ち切り誤差があります。


桁落ち誤差:非常に近い2つの値の差を求めた場合に有効桁数が減ることで引き起こされる誤差
情報落ち誤差:大きな数に小さな数を足した場合に、小さな数が大きな数の有効数字の範囲外になることで無視されることで起きる誤差
打ち切り誤差:無限級数によって表されている値の計算を打ち切ることで生まれる誤差

0 件のコメント:

コメントを投稿