SQL与C#的舍入差异:如何让SQL实现7.25舍入为7.2?
解决SQL与C#舍入结果对齐的问题
这个问题太典型了!核心原因是C#的Math.Round默认采用「银行家舍入法」(四舍六入五成双),而SQL的ROUND函数默认是「四舍五入,中间值远离零」,所以才会出现7.25在两边结果不一致的情况。要让SQL也输出7.2且不用修改C#代码,你可以试试下面几种方案:
方法1:手动实现银行家舍入逻辑
直接通过CASE表达式模拟C#的MidpointRounding.ToEven规则,逻辑是:当要舍入的中间值(比如7.25的第2位小数是5)前一位是偶数时舍去,奇数时进一位。
DECLARE @targetValue DECIMAL(18,2) = 7.25; DECLARE @decimalPlaces INT = 1; SELECT CASE -- 先将数值放大到整数位,判断中间值情况 WHEN (@targetValue * POWER(10, @decimalPlaces + 1)) % 10 = 5 THEN CASE -- 取整后判断奇偶,偶数则向下舍,奇数则向上舍 WHEN FLOOR(@targetValue * POWER(10, @decimalPlaces)) % 2 = 0 THEN FLOOR(@targetValue * POWER(10, @decimalPlaces)) / POWER(10, @decimalPlaces) ELSE CEILING(@targetValue * POWER(10, @decimalPlaces)) / POWER(10, @decimalPlaces) END ELSE -- 非中间值正常使用ROUND ROUND(@targetValue, @decimalPlaces) END AS AlignedRoundedValue;
执行这段代码会返回7.2,完美和C#的结果对齐。
方法2:简化版中间值修正
如果场景比较简单(比如固定保留1位小数),可以用更简洁的写法:当遇到x.x5的情况时,先减去一个极小值再调用ROUND,触发向下舍入:
SELECT CASE WHEN 7.25 * 100 % 10 = 5 THEN ROUND(7.25 - 0.01, 1) ELSE ROUND(7.25, 1) END AS RoundedValue;
这个写法的核心是:7.25减去0.01变成7.24,此时ROUND(7.24,1)自然会得到7.2。
方法3:封装成自定义函数(复用优先)
如果需要在多个地方使用这个规则,建议封装成SQL自定义函数,方便调用:
CREATE FUNCTION dbo.RoundToEven(@value DECIMAL(18,6), @decimals INT) RETURNS DECIMAL(18,6) AS BEGIN DECLARE @scaledValue DECIMAL(18,6) = @value * POWER(10, @decimals); DECLARE @integerPart INT = FLOOR(@scaledValue); DECLARE @fractionPart DECIMAL(18,6) = @scaledValue - @integerPart; -- 仅处理中间值(0.5)的情况 IF @fractionPart = 0.5 BEGIN RETURN CASE WHEN @integerPart % 2 = 0 THEN @integerPart / POWER(10, @decimals) ELSE (@integerPart + 1) / POWER(10, @decimals) END; END ELSE BEGIN RETURN ROUND(@value, @decimals); END END;
调用示例:
SELECT dbo.RoundToEven(7.25, 1); -- 返回7.2 SELECT dbo.RoundToEven(7.35, 1); -- 返回7.4(3是奇数,中间值进一位)
内容的提问来源于stack exchange,提问作者alwaysabeginner
相关产品推荐
相关产品推荐

