Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 除法后十进制的Linq到SQL四舍五入_Sql Server_Linq_Decimal_Rounding - Fatal编程技术网

Sql server 除法后十进制的Linq到SQL四舍五入

Sql server 除法后十进制的Linq到SQL四舍五入,sql-server,linq,decimal,rounding,Sql Server,Linq,Decimal,Rounding,在计算两个度量单位之间的比率时,我遇到了一个精度问题 比率以计量单位表的形式存储在SQL Server数据库中,格式为:NumberOfDefaultUnits decimal(28,18) 在我的linqPad示例中,我有一个类来演示哪里出了问题 private class Test { public decimal saleUom { get; set; } public decimal piUom { get; set; } public decimal Ratio

在计算两个度量单位之间的比率时,我遇到了一个精度问题

比率以计量单位表的形式存储在SQL Server数据库中,格式为:NumberOfDefaultUnits decimal(28,18)

在我的linqPad示例中,我有一个类来演示哪里出了问题

 private class Test
 {
   public decimal saleUom { get; set; }
   public decimal piUom { get; set; }

   public decimal RatioRight { get; set; }
   public decimal RatioWrong { get; set; }
   public decimal CalcledAlsoRight { get { return saleUom / piUom; } }
}
void Main() {

}

结果是:

saleUom 453.592370000000000000 
piUom 1000000.000000000000000000 
RatioRight 0.000453592370000000000 
RatioWrong 0.0004535923 
CalcledAlsoRight 0.00045359237 
花了一段时间才弄明白,必须将除数乘以1m才能得到正确的结果。如果把鞍数乘以1m,它会变得更奇怪。 结果是:

RatioRight = (sellUom * 1m) / (buyUom)
RatioRight 0.000453 
我猜这与SQLServer如何存储十进制数(28,18)以及Linq如何转换divide命令有关

更新:所有值都是小数

更新2: 看起来这完全是SQL舍入的问题。从等式中删除.Net

 select top 1 uom.NumberOfDefaultUnits
      from UnitOfMeasures uom
      where uom.Id = 13

 select (select top 1 uom.NumberOfDefaultUnits
      from UnitOfMeasures uom
      where uom.Id = 13 ) 
    / 
      (select top 1 uom.NumberOfDefaultUnits
      from UnitOfMeasures uom
      where uom.Id = 9)
第一个查询返回:453.5923700000000000


第二个:0.0004535923

看起来SQL就是这样处理这些声明的十进制大小被彼此除的

 DECLARE @p2 Decimal(28,18) = 1000000
 DECLARE @p3 Decimal(28,18) = 453.59237

 select @p3 / @p2

 DECLARE @p1 Decimal(19,18) = 1  -- This is how Linq sends the * 1m

 select @p3 / (@p2 *@p1)
 select (@p3 *@p1) / @p2
结果:

0.0004535923

0.000453


0.00045359

看起来SQL就是这样处理这些声明的十进制大小被彼此除的

 DECLARE @p2 Decimal(28,18) = 1000000
 DECLARE @p3 Decimal(28,18) = 453.59237

 select @p3 / @p2

 DECLARE @p1 Decimal(19,18) = 1  -- This is how Linq sends the * 1m

 select @p3 / (@p2 *@p1)
 select (@p3 *@p1) / @p2
结果:

0.0004535923

0.000453


0.00045359

这肯定是由于SQL Server在计算中处理精度和比例的方式

如果将@mikeymouses示例更改为@p1使用6分制,则会得到一致的结果:

DECLARE @p2 Decimal(28,6) = 1000000
DECLARE @p3 Decimal(28,18) = 453.59237

 select @p3 / @p2

 DECLARE @p1 Decimal(19,18) = 1  -- This is how Linq sends the * 1m

 select @p3 / (@p2 *@p1)
 select (@p3 *@p1) / @p2
结果:

0.00045359237000000000000

0.00045359237000

0.000453592370000000000

精度和比例结果记录在上,但关键点是: 对于乘法:

  • 结果精度=p1+p2+1
  • 结果比例=s1+s2
关于分部:

  • 结果精度=p1-s1+s2+max(6,s1+p2+1)
  • 结果比例=最大值(6,s1+p2+1)
其中p1和p2是操作数的精度,s1、s2是操作数的刻度

应记住,结果精度和刻度绝对最大值为38。当结果精度大于38时,相应的比例将减小,以防止结果的整数部分被截断。
我认为这就是这里发生的事情。

这肯定是由于SQL Server在计算中如何处理精度和规模

如果将@mikeymouses示例更改为@p1使用6分制,则会得到一致的结果:

DECLARE @p2 Decimal(28,6) = 1000000
DECLARE @p3 Decimal(28,18) = 453.59237

 select @p3 / @p2

 DECLARE @p1 Decimal(19,18) = 1  -- This is how Linq sends the * 1m

 select @p3 / (@p2 *@p1)
 select (@p3 *@p1) / @p2
结果:

0.00045359237000000000000

0.00045359237000

0.000453592370000000000

精度和比例结果记录在上,但关键点是: 对于乘法:

  • 结果精度=p1+p2+1
  • 结果比例=s1+s2
关于分部:

  • 结果精度=p1-s1+s2+max(6,s1+p2+1)
  • 结果比例=最大值(6,s1+p2+1)
其中p1和p2是操作数的精度,s1、s2是操作数的刻度

应记住,结果精度和刻度绝对最大值为38。当结果精度大于38时,相应的比例将减小,以防止结果的整数部分被截断。
我想这就是这里发生的事情。

看起来
buyum
是一个
整数。我敢打赌这一定与此有关。如果将其与
1m
相乘,则会将其转换为
十进制
。在这种情况下,我不确定小数除以整数的效果是什么。@Honeybager不,buyUom是一个小数。它直接来自计量单位表中的十进制(28,18)列。将添加一个屏幕快照您能看看
buyum
的值是多少吗?它可能与分配给
piUom
时的值不同(关于有效数字)。@honeybacker piUom的值是多少?在数据库中显示为“1000000.000000000000000000000000”。我不认为这是一个价值观问题。看看Calcledalsorlight酒店。它运行100%相同的东西“saleUom/piUom”,它得到了正确的答案,但发送到SQL的版本得到了错误的答案。我认为这与重要数字有关。NET中的一个十进制数有28-29个有效数字,在sql中,不管您定义它们的数量是多少,所以在您的例子中它将是18。这就是为什么我希望
buyum
piUom
具有不同数量的有效数字。当小数被除时,计算得到的精度和刻度。我不知道.NET是如何做到这一点的,但我相当确信您的问题是由此引起的。当您乘以
1m
时,有效数字将再次设置为.NET默认值(28-29),这将改变结果的精度和比例。看起来
buyUom
是一个
整数。我敢打赌这一定与此有关。如果将其与
1m
相乘,则会将其转换为
十进制
。在这种情况下,我不确定小数除以整数的效果是什么。@Honeybager不,buyUom是一个小数。它直接来自计量单位表中的十进制(28,18)列。将添加一个屏幕快照您能看看
buyum
的值是多少吗?它可能与分配给
piUom
时的值不同(关于有效数字)。@honeybacker piUom的值是多少?在数据库中显示为“1000000.000000000000000000000000”。我不认为这是一个价值观问题。看看Calcledalsorlight酒店。它运行100%相同的东西“saleUom/piUom”,它得到了正确的答案,但发送到SQL的版本得到了错误的答案。我认为这与重要数字有关。NET中的一个十进制数有28-29个有效数字,在sql中,不管您定义它们的数量是多少,所以在您的例子中它将是18。这就是为什么我希望
buyum
piUom
具有不同数量的有效数字。当小数被除时,结果精度和sc