5

いくつかの金融関連の SQL コードをデバッグすると、numeric(24,8) 数学の精度に関する奇妙な問題が見つかりました。

MSSQL で次のクエリを実行すると、A + B * C 式の結果が 0.123457 になります。

SELECT A, B, C, A + B * C FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A, CAST(0 AS NUMERIC(24,8)) AS B, CAST(500 AS NUMERIC(24) ,8)) AS C ) T

したがって、2 つの重要なシンボルを失いました。これをさまざまな方法で修正しようとすると、中間乗算結果(ゼロです!)から数値(24,8)への変換がうまくいくことがわかりました。

そして最後に解決策があります。しかし、まだ質問があります。MSSQL がこのように動作する理由と、サンプルで実際に発生した型変換は何ですか?

4

3 に答える 3

7

float型の加算が不正確であるのと同様に、精度を超えると、10進型の乗算が不正確になる(または不正確になる)可能性があります。データ型変換および10進数と数値を参照してください。

とを掛けるNUMERIC(24,8)NUMERIC(24,8)、SQL Serverはコンテンツではなくタイプのみをチェックするため、48桁すべての精度を保存できない場合(最大は38)、潜在的な16桁の10進数以外(24〜8)を保存しようとします。 )。それらの2つを組み合わせると、32の10進数以外の数字が得られ、10進数の6桁(38〜32)だけが残ります。

したがって、元のクエリ

SELECT A, B, C, A + B * C
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
  CAST(0 AS NUMERIC(24,8)) AS B,
  CAST(500 AS NUMERIC(24,8)) AS C ) T

に減少します

SELECT A, B, C, A + D
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
  CAST(0 AS NUMERIC(24,8)) AS B,
  CAST(500 AS NUMERIC(24,8)) AS C,
  CAST(0 AS NUMERIC(38,6)) AS D ) T

繰り返しになりますが、との間NUMERIC(24,8)NUMERIC(38,6)、SQL Serverは非小数点の潜在的な32桁を保存しようとするため、次のようA + Dになります。

SELECT CAST(0.12345678 AS NUMERIC(38,6))

0.123457丸めた後に得られます。

于 2008-09-24T10:54:31.947 に答える
0

eed3si9nによって指摘された論理とあなたの質問であなたが言ったことに従うと、数学演算を行うときの最良のアプローチは、それらを関数に抽出し、さらに各演算の後に精度を指定することであるようです。

この場合、関数は次のようになります。

create function dbo.myMath(@a as numeric(24,8), @b as numeric(24,8), @c as numeric(24,8))
returns  numeric(24,8)
as
begin 
    declare @d as numeric(24,8)
    set @d = @b* @c
    return @a + @d
end
于 2008-09-24T12:02:14.873 に答える
0

Precision、Scale、および Length (Transact-SQL) に記載されているにもかかわらず。除算などと同じように、乗算の結果の NUMERIC 型に最小の「スケール」(小数点以下の桁数) 6 を適用していると思います。

于 2013-06-04T09:43:21.743 に答える