21432


以下はSQLServerで扱っているデータです｡  
SET @Value = (0.2 +4.3+5.1+4.3+9.9+0.5+0.5)  
とした場合､@Valueの値は2.480000000000000e+002となっています｡

この値に100を掛ける､  
FLOOR(@Value)とする  
@Valueを100で割り戻す

となぜか､  
2.470000000000000e+002となってしまいます｡  
なぜ､値が減るのか､どうしてもわかりません｡

どなたか､ご教授お願いします｡


CC BY-SA 3.0
2016-01-28T06:44:26.373
21427
2016-01-28T07:52:52.947
2016-01-28T07:26:33.097
4236
12388
question
sql-server
小数の切り捨てFLOORの挙動


[小数型データ、浮動小数型データ、および実数型データの使用](https://technet.microsoft.com/ja-
jp/library/ms187912\(v=sql.105\).aspx)から引用します。

>
> 概数型では、多くの場合、指定されたとおり正確な値が格納されません。正確な値にきわめて近い概数が格納されます。多くのアプリケーションでは指定した値と格納される概数のわずかな差は問題にはなりません。ただし、その差が問題になる場合もあります。`float`
> 型と `real`
> 型にはこのような概数の性質があるので、財務アプリケーション、丸めが行われる演算、等価性のチェックなど、正確な数値動作が必要な場合には、これらのデータ型を使用しないでください。代わりに、`int`
> 型、`decimal` 型、`money` 型、`smallmoney` 型を使用してください。

の説明の通りで、`FLOOR`関数はもちろん丸めが行われる演算に該当します。


CC BY-SA 3.0
2016-01-28T07:34:15.250
21431
2016-01-28T07:34:15.250
4236
21427
answer


切り捨て誤差の影響によるものです。

2.48を2進数で表現すると、0000 0010 . 0111 1010 1110 0001 0100 0111...  
となります。 ここでは、小数点以下24桁まで書いてありますが、循環小数なのでずっと永遠に続きます。  
これは、1/3を10進数で表現すると、0.33333333...と永遠に続くのと同様です。

計算機で表現できる桁数（ビット数）には限りがありますから、どこかの桁より先は切り捨てられます。

小数点以下25桁目以降を切り捨てた 0000 0010 . 0111 1010 1110 0001 0100
0111を10進数に戻すと、2.479999959468841552734375にしかなりません。

これを100倍すると、247.9999959468841552734375。  
Floor(247.9999959468841552734375)は247となります。

このように、値を表現するのに使える桁数に限度があるために、下位の桁が切り捨てられて実際よりも小さな値になることを「切り捨て」による「誤差」と言います。

電卓で、100÷3を計算し、それに3を掛けても100にならない（99.999999....になってしまい、小数点より上を見ると99にしかならない）というのも、同様に切り捨て誤差によるものです。

＝＝  
補足：  
0.2
+4.3+5.1+4.3+9.9+0.5+0.5=24.8ですので、@valueの値は0.2480000000000000e+002もしくは2.480000000000000e+001、が正しいと思います。  
上記の説明は、2.480000000000000e+001を想定して書いてあります。


CC BY-SA 3.0
2016-01-28T07:52:52.947
21432
2016-01-28T07:52:52.947
217
21427
answer