Sql server 为什么浮点数给我的结果比十进制更准确?

Sql server 为什么浮点数给我的结果比十进制更准确?,sql-server,database,tsql,relational-database,Sql Server,Database,Tsql,Relational Database,我正在寻找一个非常准确的除法结果 此SQL返回以下结果: SELECT (CAST(297282.26 AS DECIMAL(38, 30)) / CAST(495470.44 AS DECIMAL(38, 30))) AS ResultDecimal 以下是WolframAlpha的准确结果: 我的印象是十进制比浮点更准确: 由于浮点和实数数据类型的近似性质,当需要精确的数字行为时,例如在金融应用程序中,在涉及舍入的操作中,或在等式检查中,不要使用这些数据类型。相反,请使用整数、小数

我正在寻找一个非常准确的除法结果

此SQL返回以下结果:

SELECT (CAST(297282.26  AS DECIMAL(38, 30)) / CAST(495470.44 AS DECIMAL(38, 30))) AS ResultDecimal

以下是WolframAlpha的准确结果:

我的印象是十进制比浮点更准确:

由于浮点和实数数据类型的近似性质,当需要精确的数字行为时,例如在金融应用程序中,在涉及舍入的操作中,或在等式检查中,不要使用这些数据类型。相反,请使用整数、小数、货币或smallmoney数据类型


为什么浮点计算的结果比使用十进制计算的结果更准确?

它不会给您更准确的结果。我之所以这么说是因为这个值是一个近似值,并且不是所有的值都可以存储在浮点中。然而,硬币的另一面是,浮标有可能更精确。十进制/数字的最大精度为38


当你看浮动时,最大精度是53

希望您已经理解,仅仅因为
FLOAT
版本在小数点后显示了更多的数字,并不一定意味着这些是真的数字。这是关于精确性,而不是准确性

导致精度损失的是
CAST
函数本身,而不是
FLOAT
DECIMAL
数据类型之间的差异

为了证明这一点,请将之前的结果与以下结果进行比较:

SELECT 297282.26  / 495470.44  AS ResultNoCast

在我的查询版本中,文本数字中的小数点告诉SQL Server将值视为
decimal
datatype,其长度和精度由服务器决定。结果比将显式转换为十进制时更精确

原因的线索隐藏在
CAST
函数的截断和舍入结果下:

当您转换小数位数不同的数据类型时,有时结果值会被截断,有时会被舍入。下表显示了该行为

因此,在输入过程中,每个单独的文字值都被视为一个
数字
(与
十进制
)并被转换为
数字
,这一事实导致了舍入

稍微考虑一下下一个问题,如果希望从
数值
/
十进制
数据类型得到更精确的结果,只需告诉SQL Server计算的每个组件都更精确:

SELECT 297282.26000000  / 495470.44000000  AS ResultSuperPrecise


这似乎是(从实验中)我能得到的最精确的结果:在分子或分母中添加或删除0都会使结果变得不那么精确。我无法解释为什么会这样,因为结果只有小数点右边的23位

好吧,我想是这样的

@哲学-我认为您是对的,CAST导致了问题,但这并不是因为我试图“转换小数位数不同的数据类型”

当我执行以下语句时

SELECT CAST((297282.26 / 495470.44) AS DECIMAL(38, 30)) AS ResultDecimal
计算的准确结果为:

小数点后有30多个数字,我的数据类型的刻度设置为30。因此,强制转换对值进行四舍五入,然后在末尾加上零,直到有30位数字。我们的结局是:

所以有趣的是,CAST如何确定要舍入或截断输出的小数位数?我不确定,但正如@Philogicles所指出的,输入的规模影响对输出的舍入

SELECT CAST(((297282.26/10000) / (495470.44/10000)) AS DECIMAL(38, 30)) AS ResultDecimal

想法

同样有趣的是:

然而,简单地说,当输入刻度为 高,因为需要使用 匹配精度下降

除十进制外,数字数据类型的精度和比例是固定的


我发现当您使用以下各项时,精度最好:

SELECT (CAST(297282.26  AS DECIMAL(15, 9)) / CAST(495470.44 AS DECIMAL(24, 2))) AS ResultDecimal
这导致了

0.599999991926864496699338915153

我认为实际值(到100位)是:

0.59999919268644966993389151530412187657451370862810705720405842980259326873264124495499670979362562

请记住,SQL Server将除法的最大精度和比例定义为:

最大精度=(p1-s1+s2)+最大(6,s1+p2+1)--最多38

最大刻度=最大(6,s1+p2+1)

其中p1和p2是两个数字的精度,s1和s2是数字的刻度

在这种情况下,最大精度为(15-9+2)+最大(6,9+24+1)=8+34=42

但是,SQL Server只允许最大精度为38


最大刻度=最大(6,9+24+1)=34

浮点和十进制的精度意味着不同的事情。Float—“其中n是用于存储浮点数尾数的位数”。Decimal—“将要存储的十进制数字的最大总数”,对于浮点数,53的值(n)表示精度仅为15位。对于小数点,精度(p)表示总位数,最高可达38位。浮点数表示更精确的数字,但不表示精确的数字。史蒂夫,你说得对。我没有正确计算十进制输出。在决定了我对输入精度和刻度的最低要求,以及输出所需的精度和刻度(并考虑到最大值)之后,剩下的就相对容易了。这里提供了全套精度和比例计算:这非常有用,谢谢。
SELECT CAST(((297282.26/10000) / (495470.44/10000)) AS DECIMAL(38, 30)) AS ResultDecimal
SELECT (CAST(297282.26  AS DECIMAL(15, 9)) / CAST(495470.44 AS DECIMAL(24, 2))) AS ResultDecimal