ROUTE 3390

備忘録的な用途で書いていますが、どなたかの役に立つ事があれば嬉しいです。

プログラムでの小数計算で誤差を含んでしまう原因と解決方法

Perlに限らずだいたいのプログラムでは小数点の扱いが苦手。

なぜなら浮動小数点方式というデータの持ち方をしているから。


10進数の0.1を浮動小数点方式では正確に表現出来ない(循環小数となり、途中で丸められてしまう)
そのため近似値で扱うことになり、計算結果に誤差を含むケースが出てくる。
コチラの記事が分かり易かった


では誤差を少なく計算するにはどうするか、、
これも完璧ではないようだけど、桁を上げて(揃えて)整数として計算して
最後に桁を戻すような「仮想小数点方式」で計算するのが良いらしい。


0.1 + 0.7

という計算をしたかったら


( (0.1 * 10) + (0.7 * 10) ) / 10

こうするのが「仮想小数点方式」


■ジャストアイデアだけど
仮想小数点方式でも誤差を含むっていうのは
結局0.1のような小数を使って「計算」をするから。

 

それなら
小数値を文字として扱って桁上げしたらいいんじゃないかと。
正規表現とかで頑張って、、、
=> 実際JavaBigDecimalとかはそれっぽいことしてるらしい。気が向いたら調べよう。


COBOLは小数点の計算に誤差を含まない
金融系のシステムに採用されていたりするCOBOLは小数の計算に誤差を含まない。
そんな話を昔聞いたなーっと思ったので、どうやっているか調べてみた。

BCD(Binary-coded decimal) というデータの持ち方を採用しているらしい。
詳しくはコチラの記事が大変参考になった。
ここで紹介されているパック10進数形式というのをCOBOLでは採用しているらしい。


0.1のような小数は

浮動小数点だと近似値となるけど、
BCDなら正確に表現出来る。


■まとめ
誤差を含まず「仮想小数点方式」で計算すれば、面倒だけど他の言語でも誤差を無くせるという事でいいのかな。