SQLサーバー:計算と数値リテラル
-
21-08-2019 - |
質問
った試験と浮動小数点計算を精度な損失です。見渡現象ということばを取得します。
私が書く
print 1.0 / (1.0 / 60.0)
その結果、
60.0024000960
私は同じ式にな明示的な鋳造 float
print cast(1.0 as float) / (cast(1.0 as float) / cast(60.0 as float))
その結果、
60
今まで思ったこと数値リテラルと小数点の位置を自動的に処理してい float
値が適切な精度。鋳造 real
を示しと同じ結果鋳造 float
.
- あの文書をどのようにSQLサーバーの評価数値リテラル?
- 何のデータ型はリテラル?
- だって、それを鋳型で固めてる
float
良い精度(こしきぶよう皮肉めい)? - はがきによclutteringっ式とは?
解決
SQL Serverは、可能な最小のデータ型を使用します。
このスクリプトを実行すると、
SELECT SQL_VARIANT_PROPERTY(1.0, 'BaseType')
SELECT SQL_VARIANT_PROPERTY(1.0, 'Precision')
SELECT SQL_VARIANT_PROPERTY(1.0, 'Scale')
SELECT SQL_VARIANT_PROPERTY(1.0, 'TotalBytes')
あなたはSQL Serverが暗黙的にNUMERIC(2、1)データ型を使用していることがわかります。
60.0による除算は、数値(8,6)に結果を変換する。
最終的な計算は、数値(17、10)に結果を変換します。
編集
のデータ型変換rel="noreferrer"> SQL Server Books Onlineのの
のTransact-SQLステートメントでは、一定の 小数点は自動的にあると 数値データ値に変換し、 最小精度とスケールを使用して 必要。例えば、一定の 12.345 5及びAの精度で数値に変換されます。 3の規模ます。
他のヒント
はい、あなたは頻繁に、より良い精度を得る浮くためにそれらをキャストする必要があります。それが私の感想ます:
<のhref = "http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/12/20/for-better-precision-cast-decimals-before-calculations.aspx" のrel = "nofollowをnoreferrer" >よりよい精度のために計算する
の前に小数点をキャスト私は似たようなケースでは今後の参考のために舞台裏で何が起こっているかを理解するべきだと思います。
は、科学的表記法を除く小数点リテラル数値は可能な限り最小の進数タイプとして格納されている小数点データ・タイプを表します。リーフェンKeersmaekersのと同じ引用: https://msdn.microsoft.com/en -us /ライブラリ/ ms191530%28SQL.90%29.aspx#_decimalする
のTransact-SQLステートメントでは、小数点を持つ定数であります 自動的に最小値を使用して、数値データ値に変換 精度とスケール必要。例えば、定数12.345です 5の精度および3のスケールを用いて数値に変換します。
小数点の右側の後続のゼロは、スケールを指定します。小数点の左に先頭のゼロは無視されます。
いくつかの例:
1.0 -> Decimal(2,1)
60.0 -> Decimal(3,1)
1.00 -> Decimal(3,2)
01.0 -> Decimal (2,1)
考慮すべきもう一つのポイントは、データ・タイプの優先順位です。
オペレータは、異なるデータ型の2つの式を組み合わせた場合、データ型の優先順位のルールはより低い優先順位のデータ型がより高い優先順位のデータ型に変換されることを指定します。
我々が得られた小数型、すなわち精度及びスケールの両方のオペランド及び動作自体に依存小数点タイプの算術演算を行う場合に考慮すべき更に別の点です。これは、精度、スケール、長さのrel="nofollow">文書の
だから、括弧内の自分の表現の一部 精度と小数表現の規模に関する上記の規則を使用して。またバンカーの丸めたりしても使用されているために丸め。小数点および浮動小数点型が使用されているため異なる丸めに注意することが重要です。
私たちが式を続ける場合は、 そこで不一致の一部は、フロートの場合よりも小数のタイプのために使用される異なる丸めに起因するものである。 上記のルールに基づいて、カッコ内の一つだけキャストを使用するのに十分であろう。他のすべてのリテラルは、データ型の優先順位のルールに従ってfloat型に昇格されます。 そしてもう一つ重要なこと。でも、このフロート式は、正確な結果を計算しません。これは、フロントエンド(SSMSまたは何が)の値(Iは推測)精度6桁を丸め、その後、後続のゼロを切り捨てるだけようです。だから、すなわち1.000001は1になります。 簡単な、そうではありませんか?( 1.0 / 60.0 ) is evaluated to 0.016666 and the resulting type is Decimal (8,6)
1.0 / 0.016666 is evaluated to 60.002400096 and the resulting type is Decimal (17,10)
1.0 / (1.0 / cast(60.0 as float))
一定のフロート式を作成するには、科学的表記法を使用してみます:
select (1.0E0 / (1.0E0 / 60.0E0))
結果は60である。