MySQLのFLOAT型とDECIMAL型について質問です。


FLOAT型では桁数が足りないことに気付いたので、DECIMAL(20,13)に変更したのですが
ALTER TABLE `tablename` CHANGE `hoge` `hoge` DECIMAL( 20, 13 ) NULL DEFAULT NULL ;
ところがこのSQLを投げると、hogeカラムに入っていた999.999だった値が999.9990234375000に変更されてしまいます。

固定桁数の小数点表示になるので足りない部分が補足されるのはわかるのですが、元が無い値なので0で足りない部分を埋めてくるものだと思っていたのですが、そうではないのでしょうか。
この勝手に増やされた0.0000234375という値はどこから着たのでしょうか。

どなたかわかる方いらっしゃいましたらお教えいただけますと幸いです。
よろしくお願いいたします。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/07/25 17:26:05
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.1

回答回数966ベストアンサー獲得回数247

ポイント200pt

これを理解するには、浮動小数点型というものが、どういうものかを理解する必要があります。

computer programming I
上記ページが分かりやすいと思うのですが、浮動小数点型は、2進数の世界でデータを表現しているため、10 進数でキリの良い数値であっても、2進数では循環小数となってしまう場合があります。

その「2進数では循環小数」を、浮動小数点型では、決められたビット長の範囲でしか保存出来ないので、無限の桁数を有限の桁数で切り取ってしまうことになります。

この為、浮動小数点型は、人間が考えている 10 進数の数字と誤差を持っている事が多いです。10 進数表示で有効桁が数桁のうちは、誤差なく浮動小数点で表現できているように見えますが、有効桁数を大きくすると、実際には誤差が生じている事が分かります。

で、DECIMAL 型の場合は、10 進数の一桁一桁を、そのままの形で保存します。
MySQL :: MySQL 5.1 リファレンスマニュアル (オンラインヘルプ) :: 7.14.2 DECIMAL データ型の変更

つまり、浮動小数点型が2進数でデータを保持しているために生じる 10 進数との誤差が、DECIMAL 型へ変換することで現れた、ということになります。

id:n_maco2

大変分かりやすい説明ありがとうございました!
御マニュアルの「近似値」という説明を読んで、「近似値も何もそこに10進数の値がばっちり書いてあるじゃないか」と首をかしげていたのですが、オリジナルのデータは2進数なのですね。よくわかりました、ありがとうございます。
ということは、一度2進数で保存してある以上、発生する誤差はどうしようもないのですねぇ・・直接変換せずにドコかに一度値をプールしておいて、型を変えてから改めてその値を流し込む感じしか手がなさそうに思えますね。
参考になりました、ありがとうございました。

2012/07/25 17:25:56

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません