提问人:MT. 提问时间:1/8/2009 最后编辑:ChanduMT. 更新时间:5/19/2021 访问量:56955
T-SQL 十进制除法精度
T-SQL Decimal Division Accuracy
问:
有谁知道为什么,使用 SQLServer 2005
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
给我 11.74438969709659,
但是当我将分母上的小数位增加到 15 时,我得到的答案不太准确:
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
给我 11.74438969
答:
4赞
cmsjr
1/8/2009
#1
转换表达式而不是参数。
select CONVERT(DECIMAL(38,36),146804871.212533 / 12499999.9999)
38赞
gbn
1/8/2009
#2
对于乘法,我们只需将每个参数中的小数位数相加(使用笔和纸)即可计算出输出十进制位数。
但分裂只会让你大吃一惊。我现在要躺下了。
不过,在SQL方面,它完全符合预期。
--Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
--Scale = max(6, s1 + p2 + 1)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 9 + 54 = 72
--Max P = 38, P & S are linked, so (72,54) -> (38,20)
--So, we have 38,20 output (but we don use 20 d.p. for this sum) = 11.74438969709659
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 15 + 54 = 84
--Max P = 38, P & S are linked, so (84,54) -> (38,8)
--So, we have 38,8 output = 11.74438969
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
如果您也遵循此规则,如果您将每个数字对视为
- 146804871.212533000000000 和 12499999.999900000
- 146804871.212533000000000 和 12499999.999900000000000
评论
0赞
MT.
1/8/2009
谢谢。老实说,我为我的特定问题使用了 FLOAT(因为我不需要 100% 准确),但我对使用小数时发生的事情感到困惑。
2赞
Veysel Ozdemir
3/20/2016
不幸的是,SQL Server 在算术:(方面非常糟糕因此,还值得一提的是,如果需要在 t-sql 中进行乘法和除法的准确结果,最好的选择是: 定义和使用 CLR 函数。请参阅:skylinetechnologies.com/Insights/Skyline-Blog/March-2013/...,了解一个好的介绍
19赞
Vedran Kesegic
4/3/2009
#3
简而言之,使用 DECIMAL(25,13),您可以完成所有计算 - 您将获得声明的精度:小数点前 12 位,后 13 位小数位。 规则是:p+s 必须等于 38,您将处于安全状态! 为什么会这样? 因为 SQL Server 中算术的实现非常糟糕! 在他们修复它之前,请遵循该规则。
评论
0赞
MrEdmundo
11/6/2013
是否有任何参考资料可以说明为什么这对所有计算都是“好的”?
1赞
Triynko
3/27/2017
select cast(1000000 as DECIMAL(38,19)) / cast(9223372036854775807 as DECIMAL(38,19));
<< OK << 算术溢出select cast(1000000 as DECIMAL(25,13)) / cast(9223372036854775807 as DECIMAL(25,13));
18赞
sonal
12/7/2009
#4
我注意到,如果你将除数值转换为浮点数,它会给你正确的答案,即:
select 49/30 (result = 1)
将变成:
select 49/cast(30 as float) (result = 1.63333333333333)
评论
0赞
Simon P Stevens
2/27/2020
值得注意的是,您应该小心这种类型的演员,不要盲目使用。小数和浮点数以不同的方式存储数字表示形式,浮点数具有一些不直观的影响,您在执行此操作时应注意这些效果。例如: select cast(cast(0.1 as float) as decimal(38,18)) 给出输出:0.1000000000000000006 这是因为 0.1 不能用二进制准确表示,所以它存储的东西稍微偏离了。当您开始乘法或四舍五入时,这可能会产生影响,因为结果可能只是略微偏离。
6赞
Campey
10/8/2010
#5
我们对神奇的转变感到困惑,
P&S是有联系的,所以:
- (72,54) -> (38,29)
- (84,54) -> (38,8)
假设是错别字,应该是,以下是数学:(38,29)
(38,20)
i. 72 - 38 = 34, ii. 54 - 34 = 20
i. 84 - 38 = 46, ii. 54 - 46 = 8
这就是推理:
i. 输出精度减去最大精度是我们将要丢弃的数字。
ii. 然后输出比例减去我们将要扔掉的东西给我们......输出刻度中的剩余数字。
希望这能帮助其他任何试图理解这一点的人。
评论
1赞
George Joseph
2/24/2021
错别字(应该是 i. 84 - 38(不是 58) = 46,ii. 54 - 46 = 8)。这是非常有用@Campey
0赞
Campey
9/16/2021
谢谢@GeorgeJoseph,我在 5 月份就纳入了您的更正,但似乎忘记了我的谢谢!
2赞
morex
3/16/2017
#6
使用以下方法可能会有所帮助:
SELECT COL1 * 1.0 / COL2
评论
0赞
default locale
3/16/2017
你为什么这么认为?
评论