Microsoft SQL 服务器:数字常量精度
Microsoft SQL Server : numeric constants precision
我对这个结果不够精确感到困惑:
select convert(numeric(11, 10), 1 / 3.0)
0.3333330000
为什么我要十位却只有六位小数?这里我写了3.0
而不是3
来强制浮点除法而不是整数除法(1/3
的值为零)。
但是那个常量是什么类型3.0
?它似乎不是任何本机 SQL 服务器浮点类型,它们都给出不同的结果:
select convert(numeric(11, 10), 1 / convert(real, 3))
0.3333333433
select convert(numeric(11, 10), 1 / convert(double precision, 3))
0.3333333333
select convert(numeric(11, 10), 1 / convert(float, 3))
0.3333333333
直到现在,我一直尝试编写 3.0
来获取浮点常量,就像在 C 等编程语言中会发生的那样。但这不是 SQL 中的解释。发生什么事了?
答案是3.0
给出的不是浮点型常量,而是数值型常量,具体是numeric(2,1)
。您可以使用以下方式查看:
select sql_variant_property(3.0, 'basetype') as b,
sql_variant_property(3.0, 'precision') as p,
sql_variant_property(3.0, 'scale') as s
b: numeric
p: 2
s: 1
如果您明确指定此类型,您会得到相同的奇数有限精度结果:
select convert(numeric(11, 10), 1 / convert(numeric(2, 1), 3))
0.3333330000
仍然很奇怪 -- 当原始数字常量只有一位而输出类型需要十位时,我们怎么会得到六位小数?根据数值类型提升的规则我们可以看到除法表达式得到类型 numeric(8, 6)
:
select sql_variant_property(1 / convert(numeric(2, 1), 3), 'basetype') as b,
sql_variant_property(1 / convert(numeric(2, 1), 3), 'precision') as p,
sql_variant_property(1 / convert(numeric(2, 1), 3), 'scale') as s
b: numeric
p: 8
s: 6
为什么恰恰是某物与一的倒数 d.p。应该得到六个 d.p,而不是五个或七个,我不清楚,但我想 SQL 必须选择一些东西。
故事的寓意是不要在 SQL 中编写像 1.0
这样的数字常量,以期获得浮点语义。您将获得数字语义,但小数位可能太少而无用。如果你想要浮点数,写convert(1, float)
或1e
,或者使用数字类型并检查每一步计算是否有d.p的数量。你要
感谢向我指出 https://bertwagner.com/posts/data-type-precedence-and-implicit-conversions/ 的同事,其中解释了其中的一些内容。
我对这个结果不够精确感到困惑:
select convert(numeric(11, 10), 1 / 3.0)
0.3333330000
为什么我要十位却只有六位小数?这里我写了3.0
而不是3
来强制浮点除法而不是整数除法(1/3
的值为零)。
但是那个常量是什么类型3.0
?它似乎不是任何本机 SQL 服务器浮点类型,它们都给出不同的结果:
select convert(numeric(11, 10), 1 / convert(real, 3))
0.3333333433
select convert(numeric(11, 10), 1 / convert(double precision, 3))
0.3333333333
select convert(numeric(11, 10), 1 / convert(float, 3))
0.3333333333
直到现在,我一直尝试编写 3.0
来获取浮点常量,就像在 C 等编程语言中会发生的那样。但这不是 SQL 中的解释。发生什么事了?
答案是3.0
给出的不是浮点型常量,而是数值型常量,具体是numeric(2,1)
。您可以使用以下方式查看:
select sql_variant_property(3.0, 'basetype') as b,
sql_variant_property(3.0, 'precision') as p,
sql_variant_property(3.0, 'scale') as s
b: numeric
p: 2
s: 1
如果您明确指定此类型,您会得到相同的奇数有限精度结果:
select convert(numeric(11, 10), 1 / convert(numeric(2, 1), 3))
0.3333330000
仍然很奇怪 -- 当原始数字常量只有一位而输出类型需要十位时,我们怎么会得到六位小数?根据数值类型提升的规则我们可以看到除法表达式得到类型 numeric(8, 6)
:
select sql_variant_property(1 / convert(numeric(2, 1), 3), 'basetype') as b,
sql_variant_property(1 / convert(numeric(2, 1), 3), 'precision') as p,
sql_variant_property(1 / convert(numeric(2, 1), 3), 'scale') as s
b: numeric
p: 8
s: 6
为什么恰恰是某物与一的倒数 d.p。应该得到六个 d.p,而不是五个或七个,我不清楚,但我想 SQL 必须选择一些东西。
故事的寓意是不要在 SQL 中编写像 1.0
这样的数字常量,以期获得浮点语义。您将获得数字语义,但小数位可能太少而无用。如果你想要浮点数,写convert(1, float)
或1e
,或者使用数字类型并检查每一步计算是否有d.p的数量。你要
感谢向我指出 https://bertwagner.com/posts/data-type-precedence-and-implicit-conversions/ 的同事,其中解释了其中的一些内容。