我试图将微妙的计算从C#.NET迁移到TSQL,并且无论在某些情况下原始C#.NET答案是否准确,绝对每个结果都必须保持不变.
我的TSQL脚本通常可以成功解决此问题,但是,.NET中有一些我无法捕获的异常舍入行为.我将通过两个示例进行演示:
这是我要重新创建的.NET代码.
(double)Math.Round(number, 1, MidpointRounding.AwayFromZero );
double number = 6.1499999999999995; // returns 6.1
double number = 6.9499999999999993; // returns 7 (which, to me, seems inconsistent)
这是我要与上面的.NET代码对齐的TSQL代码.
SELECT ROUND(ROUND(CAST(@Score as decimal(10,1)), 16), 1)
DECLARE @Score DECIMAL(18,16) = 6.1499999999999995 -- returns 6.1
DECLARE @Score DECIMAL(18,16) = 6.9499999999999993 -- returns 6.9 (needs to be 7)
我的目标是让我的TSQL代码在第二种情况下返回7而不是6.9.有谁知道我如何做到这一点?
解决方法:
小数是一个十进制精度的数字.双不是.由于您的C#代码使用double,因此在T-SQL中复制类似行为的唯一实际方法是在T-SQL中也使用二进制浮点数-float(特别是double对应于float(53)).舍入行为并非“异常”,它遵循IEEE-754标准.
但是,如果您关心十进制精度(似乎应该如此),则应该真正推动将C#代码切换为使用十进制而不是双精度.当您想要十进制精度时,二进制浮点是一个糟糕的选择.