问题描述
当我在sql Server中运行此简单操作时:
Select 800.0 /30.0
我得到的值是26.666666,即使它四舍五入到6位数字,也应该是26.666667。 如何获得准确的计算结果?我尝试在线搜索它,然后找到了一个解决方案,在该解决方案中,我将每个操作数都转换为高精度的小数,然后再进行操作,但这对我来说并不方便,因为我进行了很多长的复杂计算。认为必须有更好的解决方案。
解决方法
在SQL Server中使用除法时,结果标度之后的任何数字都将被截断,而不是四舍五入。对于您的表达式,您有一个decimal(4,1)
和一个decimal(3,1)
,其结果为decimal(10,6)
:
Precision = p1 - s1 + s2 + max(6,s1 + p2 + 1)
Scale = max(6,s1 + p2 + 1)
结果,26.66666666666666~
被截断为26.666666
。
您可以通过增加精度和小数位数的大小来解决此问题,然后CONVERT
返回所需的精度和小数位数。例如,将decimal(3,1)
的精度和小数位数提高到decimal(5,2)
,然后转换回decimal(10,6)
:
SELECT CONVERT(decimal(10,6),800.0 / CONVERT(decimal(5,3),30.0));
这将返回26.666667
。
这可能会有所帮助:
SELECT ROUND(800.0 /30.0,5) AS RoundValue;
结果:
RoundValue
26.666670
,
我认为这是因为SQL Server将您的数字作为decimal
值(确切地说,例如6.6666和6.6667表示这些值,而不是6和三分之二)而不是float
值(可以使用近似数字)。
如果一开始就明确将其强制转换/转换为float
,则应该使计算顺利进行。
下面是一些示例,用以说明int
,decimal
和float
计算之间的区别
- 将20除以3
- 将20除以3,然后再乘以3(数学上应为20)。
SELECT (20/3) AS int_calc,(20/3) * 3 AS int_calc_x3,(CAST(20 AS decimal(10,3)) /3) AS dec_calc,3)) /3) * 3 AS dec_calc_x3,(CAST(20 AS float) /3) AS float_calc,(CAST(20 AS float) /3) * 3 AS float_calc_x3
具有以下结果
int_calc int_calc_x3 dec_calc dec_calc_x3 float_calc float_calc_x3
6 18 6.666666 19.999998 6.66666666666667 20
您可以使用
Select CAST(800.0 AS float) /30.0
结果为26.6666666666667
请注意,如果再乘以30,它将得到正确的结果,例如
Select (CAST(800.0 AS float) /30.0) * 30
结果为800。处理小数的解决方案将没有此结果。
还请注意,一旦将其作为浮点数,则它应保持浮点数,直到以某种方式转换回小数或整数(例如,以int形式保存在表中)。所以...
SELECT A.Num / 30
FROM (Select ((CAST(800.0 AS float) /30.0) * 30) AS Num) AS A
仍将产生26.6666666666667
这将有望帮助您进行长时间的复杂计算。