Help us understand the problem. What is going on with this article?

SQLアンチパターン勉強会 第九回:ラウンディングエラー(丸め誤差)

More than 1 year has passed since last update.

はじめに

本エントリーは某社内で実施するSQLアンチパターン勉強会向けの資料となります。

本エントリーで書籍「SQL アンチパターン」をベースに学習を進めます。書籍上でのサンプルコードはMySQLですが、本エントリーでのサンプルコードはT-SQLに置き換えて解説します。

ラウンディングエラーとは

 実数を2進数でエンコードして格納する浮動小数点数のデータ型を利用すると数値に丸めが発生し、正確な数値を格納できません。また、丸めが発生した状態で連続で計算を行うことで、誤差累積が大きくなります。特に積の計算で誤差が大きくなります。
 このような計算の典型が、金融システムにおける利子の複利計算になりますので、金融アプリケーションでは正確な値を使うことが極めて重要です。

有限精度・無限精度

 3分の1のような有理数は0.3333…のような循環小数で表す場合、正確な値は少数では表現できません。桁数とは数の精度であり、循環小数では無限精度が必要になります。
 この問題への妥協策は、可能な限りオリジナルに近い値、例えば0.333などの有限精度の値を使用することです。しかしこの妥協策は丸めの振る舞いによる誤差を生み出します。
1/3 + 1/3 + 1/3 = 1
0.333 + 0.333 + 0.333 = 0.999

アンチパターン:FLOATデータ型を使用する

 SQLのFLOATデータ型は、IEEE754標準にしたがって実数を2進数形式でエンコードします。IEEE754では、浮動小数点数を2進数形式で表現します。2進数形式で無限精度が必要な値は、10進数で表現される値とは異なります。
 10進数では有限精度で表せる値、例えば59.95を2進数で正確に表すには、無限精度が必要です。FLOATデータ型で無限精度は扱えないため、2進数形式で格納できる近似値を使います。その近似値を10進数形式で表すと、59.950000762939になります。
つまりデータベースのFLOAT型に格納している値は、全て有限精度で表されているとは限らず、全ての値が丸められている可能性を想定しなければなりません。

アンチパターンの見つけ方

FLOAT型,REAL型を利用しているデータベースとなります。

アンチパターンを用いてもよい場合

FLOATは、INTや、NUMERICなどのデータ型がサポートするよりも広い範囲の実数を扱う場合に適しています。
FLOATが最適なものの代表例は、科学技術計算を行なうアプリケーションです。

解決策:NUMERIC データ型を使用する

FLOATやREALなどのデータ型の代わりに、NUMERICやDECIMALを用いて、固定制度の小数点数を表すようにしましょう。

最後に

出来る限りFLOAT型は避けましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away