こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

データ型でFloatとreal の計算の違い?

教えてください。

ストアドでfloor(数量(reat) × 単価(money))=金額という計算をさせています。
そこで、200(コ)×9.4(円)=1879円と出るのです。floorで切り捨てても、1880円のはずです。flootなしでやっても、1879,9998と出ます。
何度入力しなおしても同じです。
Floatだと、1880となります。
他の計算はちゃんとできているようです(ざっと見た限りで100%確かめた訳ではありません)

理由がわからないのですが、教えてください。

投稿日時 - 2009-04-27 16:18:34

QNo.4913265

困ってます

質問者が選んだベストアンサー

floatもrealもいわゆる概数といわれるデータ型で、小数の保持には必ず誤差が生じます。

一方、SQL Serverにはデータ型の優先順位というものがあります。
http://msdn.microsoft.com/ja-jp/library/ms190309.aspx

floatもrealもmoneyより上です。
したがって、float * money, real * moneyの演算を行うと、moneyはそれぞれfloat, realに変換されてから演算に使われます。
moneyで9.4と持っていたものがreal型に変換されると、結局9,4にはなりません。
おそらく9.399999389...あたりになってしまいます。realの有効桁数は7桁しかありませんから、小数点以下7桁目以降はアテにならない数字になります。
これに200を掛けても1879.999877..などとなるため、floorを掛けても1879になってしまいます。

floatも基本は同じですが、有効桁数が15桁あります。
moneyの9.4はおそらく9.40000000000004くらいの精度で変換されます。したがってfloorを掛けても1880と出ます。

しかし、誤差が上に出るか、下に出るかは扱う数字により保証の限りではありません。
したがって、real型やfloat型を金額計算に用いるべきではありません。
numeric(decimal)で計算すべきでしょう。

#質問者さんは結果をmoney型で受け取ろうとされているようです。

投稿日時 - 2009-04-27 17:29:59

お礼

jamshid6 さん、ありがとうございます。

<小数の保持には必ず誤差が生じます>これは読んでいたのですが、
小数点第何位かをまとめるのだろうと勝手に解釈していました。
データ型で計算が違ってくるとは思ってもいませんでした。
勉強になりました。

数量を decimal(10,2)に変更します。
ありがとうございました。

投稿日時 - 2009-04-27 18:21:18

このQ&Aは役に立ちましたか?

6人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

結論がでたようですが、こちらも以下で再現しました。

できれば第三者が再現可能なソースを提示していただけると理解が早いです。

-----------
DECLARE @rReat Real
DECLARE @mMoney money

DECLARE @fReat float

set @rReat =200

set @fReat =200
set @mMoney = 9.4

select @rReat * @mMoney
select FLOOR(@rReat * @mMoney)

select @fReat * @mMoney
select FLOOR(@fReat * @mMoney)


-------------
1880
(1 行処理されました)

----------------------
1879
(1 行処理されました)

----------------------
1880
(1 行処理されました)

----------------------
1880
(1 行処理されました)

投稿日時 - 2009-04-27 18:42:20

お礼

3rd_001 さん、ありがとうございます。

Floorで切り捨てているから、中途半端な数字になるのですよね。
でも通常は1円以下の数字は切り捨てるので、Floorが便利だったのです。

また次回からはソースも提示するようにします。
本当にありがとうございました。

投稿日時 - 2009-04-28 09:15:19

ANo.1

DECLARE @rReat Real
DECLARE @rMoney Real
DECLARE @fReat float
DECLARE @fMoney float

set @rReat =200
set @rMoney =9.4
set @fReat =200
set @fMoney = 9.4

select @rReat * @rMoney
select @fReat * @fMoney
select 200*9.4

試しに上記で計算してみましたが、すべて「1880」になりました。
再現ケースを示してください。

参考:float 型と real 型 (Transact-SQL)
http://msdn.microsoft.com/ja-jp/library/ms173773.aspx

投稿日時 - 2009-04-27 17:05:43

補足

3rd_001 さん、ありがとうございます。
実際に使用しているのは、下記SQLですが、テストで新しいテーブルを作成し、数量をreal型にすると、同じ結果(1879.99988)が出ます。
単価をreat型にしても同じです。
SQLがExpressのせいでしょうか(まさか??)
私のPC,もしくはSQL固有の問題なのでしょうか?
参考リンクも読みましたが、real型で問題あるとは思えません。


begin
SELECT TOP (100) PERCENT 発注明細ID, 発注管理ID, 部品ID, 内訳, 数量, 単位, 単価, FLOOR(数量 * 単価) AS 金額, 納品, 摘要, 員数,
員数単位
FROM dbo.T_発注明細
where発注管理ID=@myid
ORDER BY 発注明細ID
end

投稿日時 - 2009-04-27 17:19:22

あなたにオススメの質問