关于十进制算术的问题

Myt*_*kos 5 sql-server datatypes decimal sql-server-2016

我认为我对精度与比例的理解可能不正确,因为以下示例产生的值对我来说没有意义。decimal(32, 14)轮结果到6位小数,而decimal(18, 14)发到19我的理解小数的是decimal(p, [s]),这里p是数字的总数,s是数字的小数点(IG后的数字,decimal(10, 2)会导致8位,左侧是小数和 2 位数字)。这不正确吗?

我创建了一个小例子来说明看似奇怪的行为:

--------------------
-- Truncates at pipe
-- 1.043686|655...
--------------------
declare @dVal1 decimal(32, 14) = 10
declare @dVal2 decimal(32, 14) = 9.581419815465469

select @dVal1 Val1, @dVal2 Val2, @dVal1 / @dVal2 CalcResult

----------------
-- Most accurate
----------------
declare @dVal3 decimal(18, 14) = 10
declare @dVal4 decimal(18, 14) = 9.581419815465469

select @dVal3 Val3, @dVal4 Val4, @dVal3 / @dVal4 CalcResult
Run Code Online (Sandbox Code Playgroud)

那么问题来了,我缺少什么来理解这一点?我读过的文章和 msdn 博客似乎没有提供清晰的信息(至少对我的思考过程而言)。有人可以向我解释为什么更高的精度似乎会导致比例损失?

scs*_*mon 3

您的理解是正确的,尽管您的数字太多@dVal2@dVal4这就是为什么您看到这些数字被四舍五入为 7 ( 9.58141981546547) 的最后一位数字select

\n\n

至于除法舍入,它隐藏在文档的中间。

\n\n
\n

在乘法和除法运算中,我们需要 precision -scale\n 位置来存储结果的整数部分。可以使用以下规则缩小规模:

\n\n

如果整数部分小于 32,则结果比例缩小为 min(scale, 38 \xe2\x80\x93 ( precision-scale))\n,因为它不能大于\n 38 \xe2\x80\x93 (精确刻度)。在这种情况下,结果可能会被四舍五入。

\n\n

如果小于 6 并且整数部分大于 32,则小数位不会更改。在这种情况下,如果无法放入小数(38,小数位数),则可能会引发溢出错误

\n\n

如果\n 大于 6 并且整数部分大于 32,则小数位数将设置为 6。在这种情况下,\n 整数部分和小数位数都会减少,结果类型为十进制(38,6 )。结果可能会四舍五入到小数点后 6 位,或者如果整数部分无法容纳 32 位数字,则会引发溢出错误。

\n
\n\n

因此,在第一种情况下decimal(32,14),比例尺被设置为 6 位数字,因为结果值decimal(64,28)的 a scale = 28> 6 并且积分部分(64-28) = 36> 32,如上面最后一条规则中所定义。因此,decimal(38,6)

\n\n

在第二种情况下decimal(18,14),第一个规则将应用于您的结果值decimal(36,28)to的比例min(28, 38 -(36-28)) = min(28,30) = 28。因此,decimal(38,28)

\n