5

他のすべての言語(一般に算術エンジン)では、同じ優先順位の演算子を括弧で囲んでも、結果に影響はありません。しかし最近、テストプロジェクトで、MSSQLサーバーがそのような場合に結果を変更することに気づきました。以下のクエリをご覧になり、アイデア(またはSQL Server管理の設定)または動作を説明するMSDNの記事へのリンクがあればお知らせください。

select (0.55 * 287.61 / 0.66) calc_no_parens
,(0.55 * (287.61 / 0.66)) calc_parens
,round(0.55 * 287.61 / 0.66,2) no_paren_round
,round(0.55 * (287.61 / 0.66),2) paren_round;

結果

Column  Record 1
calc_no_parens  239.6750000
calc_parens     239.67499985
no_paren_round  239.6800000
paren_round     239.67000000

私にとって、最初の2つは239.675を返し、ラウンドは239.68を返すはずです。

4

4 に答える 4

4

各値をとして宣言すると、目的の結果が得られますFloat

DECLARE @Float1 float, @Float2 float, @Float3 float;
SET @Float1 = 0.55;
SET @Float2 = 287.61;
SET @Float3 = 0.66;

select (@Float1 * @Float2 / @Float3) calc_no_parens
,(@Float1* (@Float2/ @Float3)) calc_parens
,round(@Float1 * @Float2/ @Float3,2) no_paren_round
,round(@Float1* (@Float2/ @Float3),2) paren_round;

出力

calc_no_parens  calc_parens no_paren_round  paren_round
239.675          239.675    239.68           239.68

この記事を見たいと思うかもしれません:いわゆる「正確な」数値はまったく正確ではありません!

于 2012-09-17T04:35:45.003 に答える
3

何が起こっているのかはわかりますが、修正はないと思います。

SQLは、関数の各部分をSQLデータ型(この場合は浮動小数点数)として計算して格納します。

287.61 /0.66は435.7727272727272727272727272...を生成します。SQLはある程度の精度で浮動小数点数として格納しますが、正確ではありません(結局のところ、浮動小数点数です)。

浮動小数点数の詳細:浮動小数点はどのように格納されますか?いつそれが重要ですか?

于 2012-09-17T04:36:21.363 に答える
0

Habibの回答により、これは私の列が使用している10進数のデータ型である必要があると思いました。少し調べてみたところ、この 精度、スケール、長さ(Transact-SQL)が見つかりました

その記事でわかるように、除算演算は、結果の小数のスケールと精度の両方を大幅に変更します。次に、クエリのバリエーションを試しましたが、今回は乗算演算の前後に括弧を追加しました。

select distinct (0.55 * 287.61 / 0.66) calc_no_parens
,(0.55 * (287.61 / 0.66)) calc_parens_div
,((0.55 * 287.61) / 0.66) calc_parens_mult
,round(0.55 * 287.61 / 0.66,2) no_paren_round
,round(0.55 * (287.61 / 0.66),2) paren_round
,round((0.55 * 287.61) / 0.66,2) paren_round2;

結果

Column              Record 1
calc_no_parens      239.6750000
calc_parens_div     239.67499985
calc_parens_mult    239.6750000
no_paren_round      239.6800000
paren_round         239.67000000
paren_round2        239.6800000

除算が数式の最後の演算子である限り、正しい答えが得られます。これは問題の修正ではありませんが、将来のテストプロジェクトで自己学習することです。

于 2012-09-17T15:57:35.407 に答える
0

数値を使用する場合、SQLはそれらを動的に変換しようとします。

{{

SELECT 
0.55*(287.61 / 0.66) PrecisionError, 
0.55* (CONVERT(NUMERIC(24,12), 287.61) / CONVERT(NUMERIC(24,12), 0.66)) NotPrecisionError

DECLARE @V SQL_VARIANT
SET @V = 0.55*(287.61 / 0.66)

SELECT 
Value = @V
,[TYPE] = CONVERT(SYSNAME, sql_variant_property(@V, 'BaseType')) + '(' + 
          CONVERT(VARCHAR(10), sql_variant_property(@V, 'Precision')) + ',' + 
          CONVERT(VARCHAR(10), sql_variant_property(@V, 'Scale')) + ')'  

SET @V = 0.55 * (CONVERT(NUMERIC(24,14), 287.61) / CONVERT(NUMERIC(24,14), 0.66))
SELECT 
Value = @V
,[TYPE] = CONVERT(SYSNAME, sql_variant_property(@V, 'BaseType')) + '(' + 
          CONVERT(VARCHAR(10), sql_variant_property(@V, 'Precision')) + ',' + 
          CONVERT(VARCHAR(10), sql_variant_property(@V, 'Scale')) + ')'

}

結果

PrecisionError NotPrecisionError

239.67499985 239.6750000000000

タイプ

239.67499985numeric(14,8)

タイプ

239.6750000000000数値(38,13)

于 2014-07-06T03:51:53.250 に答える