|
2015/03/16(Mon) 21:53:28 編集(投稿者)
■No75337 (魔界の仮面弁士) に追記 >> -2257.5999999999999 ⇒ -2257.6 >> 546.29999999999995 ⇒ 546.3 > バージョンが違うことで、文字列化したときに異なる値に見えてしまうだけで、 > 実際には同じ値ということはないでしょうか。
念のために試算。
たとえば、float(24) の範囲で、「-2257.6」の近似値をバイナリ表現してみます。 有効桁数 24 bit の 2 進小数で表すので、近傍値はこのあたりになります。
(a) -100011010001.100110011000 → 10進数の -2257.599609375 に相当 (b) -100011010001.100110011001 → 10進数の -2257.599853515625 に相当 (c) -100011010001.100110011010 → 10進数の -2257.60009765625 に相当 (d) -100011010001.100110011011 → 10進数の -2257.600341796875 に相当 (e) -100011010001.100110011100 → 10進数の -2257.6005859375 に相当
※SQL Server の内部的には、おそらく「c」のバイナリで格納されると思います。
一方、最大精度の float(53) が使われていたと仮定すると、 有効桁数 53bit なので、このあたりですね。 (x) -100011010001.10011001100110011001100110011001100110010 (y) -100011010001.10011001100110011001100110011001100110011 (z) -100011010001.10011001100110011001100110011001100110100
上記の 2 進小数を 10 進小数に直してみると、こうなります。
(X) -2257.5999999999994543031789362430572509765625 (Y) -2257.59999999999990905052982270717620849609375 (Z) -2257.600000000000363797880709171295166015625
今回の「-2257.5999999999999」も「-2257.6」も、 もっとも近い値は Y の値ですから、 実際は両値とも、同じバイナリであると言えるでしょう。
=== 以下蛇足 ===
上記だけ見ると、X と Y は 17 桁ぐらいの精度をもっているかのようにも 見えますが、それはたまたたま、そういう数値域にあったというだけです。
内部的には、最大でも「53 bit 分」の有効桁数しかありません。
「53 bit」で表せる値の範囲は、符号無し10進整数で「0〜9007199254740991」の 範囲です。すなわち約 15.9 桁が、最大精度ということですね。
この15桁(53bit)の数値列に対し、何桁目に小数点を打つのかという形で 値を管理しているのが、『浮動小数点型』である float(53)型 です。
=== 蛇足ここまで ===
もしも、10 進数表記での誤差を抑える必要があるのなら、float ではなく、 『固定小数点型』である decimal 型を使ってみてください。 これならば誤差が出る心配はありません。
元データが float 型である以上、今更型を変更してみたところで、 既存のデータの誤差を解消できるわけではありませんが、 今後の事を考えれば、データ型を見直すことも必要かと。
|