我正试图解释101.10的价值差异。
303'300'000 / 12约为25'275'000。
但是,根据MS-SQL,它是25'274'898.90。
请考虑以下SQL语句:
SELECT
303300000.00/12.0 AS a
,1.0/12.0*303300000.00 AS b
,1.0/12.0 AS omg
,1.0/CAST(12.0 AS float) AS expected
,0.083333*303300000.0 AS r1
,0.083333333333333300 * 303300000.0 AS r2
我认为自从我写1.0 / 12.0以来,它会转换为 float
(这本身就是愚蠢的,但这是另一个故事),
但显然是decimal (8,6)
CREATE VIEW dbo._Test
AS
SELECT 1.0/12.0 as xxx
SELECT
COLUMN_NAME
,DATA_TYPE
,NUMERIC_PRECISION
,NUMERIC_SCALE
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '_Test'
DROP VIEW dbo._Test
这种疯狂有什么理由吗?
它如何确定精度?
是否有任何强制浮点的符号,而无需强制转换语句?
如果我在PostgreSQL上运行相同的查询,pg做对了...
答案 0 :(得分:6)
文档中对此进行了解释:Precision, scale, and Length (Transact-SQL)
具体说:
操作数表达式用精度e1表示 p1和标度s1,以及表达式e2,精度为p2和标度s2。 任何非十进制表达式的精度和小数位数为 为表达式的数据类型定义的精度和小数位数。
Operation Result precision Result scale * e1 + e2 max(s1, s2) + max(p1-s1, p2-s2) + 1 max(s1, s2) e1 - e2 max(s1, s2) + max(p1-s1, p2-s2) + 1 max(s1, s2) e1 * e2 p1 + p2 + 1 s1 + s2 e1 / e2 p1 - s1 + s2 + max(6, s1 + p2 + 1) max(6, s1 + p2 + 1)
这里的重要部分是最后一部分。就您而言,您有一个decimal(2,1)
和一个decimal(3,1)
。为了精确起见,这导致:
2 - 1 + 1 + max(6,1 + 3 + 1) = 2 + max(6,5) = 2 + 6 = 8
对于规模,我们得到:
max(6,1+3+1) = max(6,5) = 6
取结果值,结果得到一个decimal(8,6)
。
答案 1 :(得分:2)
设置decimal
/ numeric
的乘法和除法的精度和小数位数是一个神秘的艺术。 SQL Server确实在documentation中解释了基本原理:
在乘法和除法运算中,我们需要精度-标度 存储结果不可分割部分的位置。规模可能是 减少使用以下规则:
如果整数部分小于32,则所得的比例会减小为min(scale,38 –(precision-scale)),因为 不能大于38 –(精度标度)。结果可能会四舍五入 在这种情况下。
如果小数位小于6并且整数部分大于32,则不会更改刻度。在这种情况下,可能会出现溢出错误 如果它不能适合小数(38,小数位数),将被提高
如果小数位数大于6并且整数部分大于32,则小数位将设置为6。在这种情况下,整数部分和 小数位数将减少,结果类型为小数(38,6)。结果 可能会四舍五入到小数点后六位或抛出溢出错误 如果整数部分不能容纳32位数字。
因为我从来不需要实现此功能,所以我必须坦白地说,我不确定我是否真的了解逻辑(我相信这很有意义)。我从解释中得出的结论是:如果我关心结果的精度和小数位数,那么我将在算术运算之后进行转换。
在该解释的某个地方,我看到“ 6”,因此解释了比例尺部分。我确信精度来自同样直接的逻辑。
答案 2 :(得分:0)
请考虑以下事实:literals like 1.0 and 12.6 are of decimal (numeric) type。 1.0是精度2和小数位1,12.0是精度3和小数位2。
表达式1.0 / 12.0的结果为类型十进制(数字)because the highest precendence of the types is decimal(两种类型均为十进制)。
对于precision and scale of the expression,公式为:
expr precision scale
e1 / e2 p1 - s1 + s2 + max(6, s1 + p2 + 1) max(6, s1 + p2 + 1)
所以
precision = 2-1 + 1 + max(6,1 + 3 + 1)= 2-1 + 1 + 6 = 8
和
scale = max(6,1 + 3 + 1)= 6