提问人:Ed Avis 提问时间:12/17/2020 最后编辑:Ed Avis 更新时间:12/22/2020 访问量:101
Microsoft SQL Server:数值常量精度
Microsoft SQL Server : numeric constants precision
问:
我对这个结果缺乏精确性感到困惑:
select convert(numeric(11, 10), 1 / 3.0)
0.3333330000
为什么我问十位时只有小数点后六位?在这里,我写的不是强制浮点除法而不是整数除法(的值为零)。3.0
3
1/3
但是这个常数是什么类型?它似乎不是任何本机 SQL Server 浮点类型,它们都给出了不同的结果:3.0
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
到目前为止,我一直试图编写以获得浮点常量,就像在 C 等编程语言中发生的那样。但这不是 SQL 中的解释。发生了什么事情?3.0
答:
0赞
Ed Avis
12/17/2020
#1
答案是,没有给出浮点类型的常量,而是给出一个数值类型的常量,特别是 .您可以使用以下方式查看此内容: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. 的倒数应该得到 6 d.p.,而不是 5 或 7,但我想 SQL 必须选择一些东西。
这个故事的寓意不是像在 SQL 中那样编写数字常量来期望获得浮点语义。你会得到数字语义,但小数点后太少而没有用。如果你想要浮点数,可以写成,或者使用数字类型,并检查计算的每个步骤是否都有你想要的d.p.数。1.0
convert(1, float)
1e
感谢同事们向我指出 https://bertwagner.com/posts/data-type-precedence-and-implicit-conversions/ 这解释了其中的一些原因。
评论
0赞
Jeroen Mostert
12/17/2020
除了强制转换之外,该表示法还可用于获取浮点文字(或仅 )。在原始示例中,给出 FP 结果。e
3e0
3e
SELECT 1e / 3
0赞
Ed Avis
12/17/2020
谢谢,我已将您的建议纳入答案。
评论