Sql server SQL server 2005数字精度损失

Sql server SQL server 2005数字精度损失,sql-server,floating-point,type-conversion,casting,floating-accuracy,Sql Server,Floating Point,Type Conversion,Casting,Floating Accuracy,调试一些与金融相关的SQL代码时发现了一个奇怪的数字(24,8)数学精度问题 在MSSQL上运行以下查询,将得到+B*C表达式结果为0.123457 选择一个, B C A+B*C 从…起 ( 选择强制转换(0.12345678作为数字(24,8))作为, 将(0作为数字(24,8))转换为B, 铸造(500为数字(24,8))为C )T 所以我们失去了两个重要的符号。尝试用不同的方法修复这个问题,我得到了中间乘法结果(零!)到数字(24,8)的转换将很好 最后,我有一个解决方案。但我仍然有一个

调试一些与金融相关的SQL代码时发现了一个奇怪的数字(24,8)数学精度问题

在MSSQL上运行以下查询,将得到+B*C表达式结果为0.123457

选择一个, B C A+B*C 从…起 ( 选择强制转换(0.12345678作为数字(24,8))作为, 将(0作为数字(24,8))转换为B, 铸造(500为数字(24,8))为C )T

所以我们失去了两个重要的符号。尝试用不同的方法修复这个问题,我得到了中间乘法结果(零!)到数字(24,8)的转换将很好


最后,我有一个解决方案。但我仍然有一个问题-为什么MSSQL会以这种方式运行,以及在我的示例中实际发生了哪些类型转换?

正如浮点类型的加法不准确一样,如果超出精度,十进制类型的乘法可能不准确(或导致不准确)。见和

由于您将
数值(24,8)
数值(24,8)
相乘,并且SQL Server将只检查类型而不是内容,因此当无法保存所有48位精度(最大值为38)时,它可能会尝试保存可能的16位非十进制数字(24-8)。将这两个数字组合起来,得到32个非十进制数字,剩下的只有6个十进制数字(38-32)

因此,原始查询

SELECT A, B, C, A + B * C
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
  CAST(0 AS NUMERIC(24,8)) AS B,
  CAST(500 AS NUMERIC(24,8)) AS C ) T
减少到

SELECT A, B, C, A + D
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
  CAST(0 AS NUMERIC(24,8)) AS B,
  CAST(500 AS NUMERIC(24,8)) AS C,
  CAST(0 AS NUMERIC(38,6)) AS D ) T
同样,在
NUMERIC(24,8)
NUMERIC(38,6)
之间,SQL Server将尝试保存可能的32位非小数,因此
A+D
减少为

SELECT CAST(0.12345678 AS NUMERIC(38,6))

在四舍五入后得到
0.123457

按照您在问题中指出的逻辑和所说的,似乎进行数学运算的最佳方法是将它们提取到函数中,并在每次运算后指定精度

在这种情况下,函数可能类似于:

create function dbo.myMath(@a as numeric(24,8), @b as numeric(24,8), @c as numeric(24,8))
returns  numeric(24,8)
as
begin 
    declare @d as numeric(24,8)
    set @d = @b* @c
    return @a + @d
end

不管上面怎么说。我认为,它还将乘法的最小“小数位数”(小数位数)设置为6,与除法等相同。

这种方法可能无法解决SQL Server截断小数部分的问题。为了保存小数部分,可能需要将@a和@b转换为double。谢谢,在使用SQL进行精确数学计算时,我会记住这一点,到目前为止,我还不需要使用它,但现在很好,可能需要考虑一些问题。您指的是数字(32,6))??如果总数必须是38@Edmondo1984请阅读链接并理解这两个数字的含义。您说当两个数字(24,8)相乘时,服务器将尝试保存16位并生成(32,6),它如何变成38,6?Thanks@Edmondo1984在
NUMERIC(p,s)
中,
p
表示总位数的精度。所以在
数字(24,8)
中有16位非小数。没有比特。同样,请阅读msdn文档的链接。