我正在寻找一个非常准确的除法结果。
此SQL返回以下结果:
SELECT (CAST(297282.26 AS DECIMAL(38, 30)) / CAST(495470.44 AS DECIMAL(38, 30))) AS ResultDecimal
SELECT (CAST(297282.26 AS FLOAT) / CAST(495470.44 AS FLOAT)) AS ResultFloat
以下是WolframAlpha的准确结果: http://www.wolframalpha.com/input/?i=297282.26%2F495470.44
我的印象是DECIMAL比FLOAT更准确:
“由于float和实际数据类型的近似性质,当需要精确的数字行为时,不要使用这些数据类型,例如在财务应用程序,涉及舍入的操作或相等检查中。 ,使用整数,小数,金钱或小数据数据类型。“
https://technet.microsoft.com/en-us/library/ms187912(v=sql.105).aspx
为什么FLOAT计算比使用DECIMAL时更准确?
答案 0 :(得分:2)
我发现你使用时的最佳精确度是:
SELECT (CAST(297282.26 AS DECIMAL(15, 9)) / CAST(495470.44 AS DECIMAL(24, 2))) AS ResultDecimal
这给出了
的结果0.599999991926864496699338915153
我认为实际值(到100位)是:
... 0.5999999919268644966993389151530412187657451370862810705720405842980259326873264124495499670979362562
请记住,SQL Server将划分的最大精度和比例定义为:
最大精度=(p1 - s1 + s2)+ MAX(6,s1 + p2 + 1) - 最多38
max scale = MAX(6,s1 + p2 + 1)
p1& p2是两个数字的精度,s1& s2是数字的比例。
在这种情况下,最大精度为(15-9 + 2)+ MAX(6,9 + 24 + 1)= 8 + 34 = 42.
但是,SQL Server仅允许最大精度为38。
最大比例= MAX(6,9 + 24 + 1)= 34
答案 1 :(得分:1)
它没有为您提供更准确的结果。我这样说是因为该值是近似值,并非所有值都可用于存储在浮点数中。在那个硬币的另一边,浮子有可能更精确。小数/数字的最大精度为38. https://msdn.microsoft.com/en-us/library/ms187746.aspx
当您查看浮点数时,最大精度为53. https://msdn.microsoft.com/en-us/library/ms173773.aspx
答案 2 :(得分:1)
希望您已经明白,仅仅因为FLOAT
版本在小数点后面显示更多数字,并不一定意味着那些是真正的数字。这是关于精度,而不是准确度。
CAST
函数本身导致精度损失,而不是FLOAT
和DECIMAL
数据类型之间的差异。
为了证明这一点,请将您之前的结果与以下结果进行比较:
SELECT 297282.26 / 495470.44 AS ResultNoCast
在我的查询版本中,文字数字中存在小数点表示SQL Server将值视为DECIMAL
数据类型,具有服务器确定的适当长度和精度。结果比CAST
明确DECIMAL
时更精确。
隐藏在CAST
函数的official documentation隐藏在截断和舍入结果下的
转换小数位数不同的数据类型时,有时会截断结果值,有时会舍入结果值。下表显示了该行为。
From | To | Behavior
numeric | numeric | Round
因此,在进入NUMERIC
的过程中,每个单独的文字值被视为DECIMAL
(与NUMERIC
相同)的事实会导致舍入。
稍微预测下一个问题,如果您想从NUMERIC
/ DECIMAL
数据类型获得更精确的结果,您只需告诉SQL Server计算的每个组成部分都更精确:< / p>
SELECT 297282.26000000 / 495470.44000000 AS ResultSuperPrecise
这看起来(来自实验)是我能得到的最精确的:从分子或分母中添加或删除0会使结果不那么精确。我无法解释为什么会这样,因为结果只是小数点右边的23位数。
答案 3 :(得分:0)
好的,这就是我的想法。
@philosophicles - 我认为你是正确的,因为CAST导致问题,但不是因为我试图转换小数位不同的数据类型&#34;。
当我执行以下声明时
SELECT CAST((297282.26 / 495470.44) AS DECIMAL(38, 30)) AS ResultDecimal
计算的准确结果是
小数点后面的位数超过30位,我的数据类型的比例设置为30.因此CAST对值进行舍入,然后只将末尾添加零,直到有30位数。我们最终得到了这个:
有趣的是,CAST如何确定要舍入或截断输出的小数位数?我不确定,但正如@philosophicles指出的那样,输入的比例会影响输出的舍入。
SELECT CAST(((297282.26/10000) / (495470.44/10000)) AS DECIMAL(38, 30)) AS ResultDecimal
思想?
同样有趣:
但是,简单来说,输入音阶时精度会丢失 因为结果比例需要降低到38 匹配精度下降。
https://dba.stackexchange.com/questions/41743/automatic-decimal-rounding-issue
除十进制之外的数值数据类型的精度和比例是固定的。
https://dba.stackexchange.com/questions/41743/automatic-decimal-rounding-issue