【基】浮動小数点数(桁落ち、オーバフロー、丸め誤差、情報落ち)

◆雑なまとめ

丸め誤差:四捨五入・切り上げ・切り捨てで生じる誤差

オーバフロー:扱える数値の最大値を超えることで生じるエラー

桁落ち(アンダーフロー):値が近い二つの数を引き算することにより,不正な値が現れること

情報落ち:絶対値が大きな値と小さな値とを加えた場合,小さい方の数値がもつ情報が失われること


◆浮動小数点数

画像4


10進数表記:0.00000000000000000000123456789 = 1.23456789 * 10^(-21)

2進数表記: 0.00000000000000000000000001101101001 = 1.101101001 * 2^(-26)

仮数部:「1.23456789」「1.101101001」 

指数部:「-21」「-26」 

画像1

float 型の精度(有効桁数)は2進数にして 24 (=23+1) 桁であり,10進数では約 6 ~ 7 桁となる.

画像2

double 型の精度(有効桁数)は2進数にして 53 (=52+1) 桁であり,10進数では約 14 ~ 15 桁となる.


◆丸め誤差

浮動小数点数の演算結果について、最小の桁よりも小さい部分の四捨五入・切り上げ・切り捨てを行うことによって生じる誤差のこと。


例:java実践

double d = 0.123456789f;

System.out.println(d); ->コンソール表示「0.12345679」(0.123456789ではない)


◆オーバフロー

演算結果が、扱える数値の最大値を超えることによって生じるエラーのこと。

例:java実践

int i = 128; <- (0b1000_0000であり、byteの最大値を超過する)

byte b = (byte)i; <- (byteの最大値127だが・・・)

System.out.println(i); -> コンソール表示「-128」(127ではない)



◆桁落ち(アンダーフロー)

値が ほぼ等しい浮動小数点数同士の減算において、有効桁数が大幅に減ってしまうこと。(値が近い二つの数を引き算することにより,その有効桁数が落ち、不正な値が現れること)


例:java実践

float f1 = 2.00000001f;

float f2 = 2.0f;

System.out.println(f1 - f2) ->コンソール表示「0.0」(0.00000001ではない)

結果:「2.00000001」が「0.00000001」へと変化した時、仮数部で表現する値は「2.00000001」から「1」に変化する。「0.00000001」の「0.0000000」の範囲は全て0のため仮数部ではなく指数部で「小数部8桁」という形で表現される。
仮数部では「2.0000000」の範囲がなくなったため、仮数部の計算結果はビット的に左にずれる。ずれた結果、空いた右側のビットには0が埋められる。
だが、この0は正しい値ではない。「2.00000001」を表す仮数部のビット表現は、本当であれば無限に続くビットで表現するべきもので、それをやむなく仮数部のサイズで切り落としているだけだからである。
結果、0で埋められた範囲の桁は「誤った値を持つ桁」となり、正しい桁を持つ範囲が狭まることになる。つまり「桁が減る」ことになり、これを「桁落ち」という。


◆情報落ち

浮動小数点数の加算において、一方の数値の下位の桁が結果に反映されないこと。(絶対値が大きな値と小さな値とを加えた場合,小さい方の数値がもつ情報が失われること)

例:java実践

float f1 = 77777.7f;

float f2 = 1.23456f;

System.out.println(f1 + f2); -> コンソール表示「77778.9」(77778.93456ではない)

結果:1.23456 がもつ情報のうちの下4桁の情報が失われている.


この記事が気に入ったらサポートをしてみませんか?