SQL Server与C#数值计算结果差异问题 如何获取一致的高精度结果
问题原因
你遇到的差异本质是SQL Server不同数值类型运算的精度截断/舍入规则和C#默认decimal运算规则的差异:
- SQL中
@decImporteCuota * CAST(26 AS INT)是DECIMAL(18,5)和INT类型运算,隐式转换后的运算结果小数位保留规则会让中间结果的舍入更偏向进一位,最终得到6.89500 - 而SQL中直接写26、以及C#默认直接用decimal乘26的时候,运算中间值的舍入规则是截断或者向偶舍入,刚好把末尾的极小值舍去,最终得到6.89499
解决方案
C#中可以通过显式控制中间计算的舍入规则,匹配SQL中INT乘DECIMAL(18,5)的逻辑来得到预期结果:
// 变量类型严格匹配SQL定义,金额类用decimal,份数用int decimal decImporteCuota = 65.20091m; decimal decImporteSA = 1820.76533m; int intCantCuotas = 26; // 中间乘法运算显式保留5位小数,匹配SQL DECIMAL(18,5)的精度规则,使用四舍五入匹配SQL默认舍入逻辑 decimal multiplyResult = Math.Round(decImporteCuota * intCantCuotas, 5, MidpointRounding.AwayFromZero); // 最终结果同样舍入到5位小数,和SQL返回类型一致 decimal decPorcDescuentoTotal = Math.Round(100 * (1 - multiplyResult / decImporteSA), 5, MidpointRounding.AwayFromZero); // 输出结果为 6.89500 Console.WriteLine(decPorcDescuentoTotal.ToString("F5"));
关键说明
- 所有参与运算的变量优先匹配SQL的类型定义,避免隐式转换带来的精度误差
- 显式指定
MidpointRounding.AwayFromZero(四舍五入)替代C#默认的向偶舍入,和SQL Server的舍入规则对齐 - 中间和最终结果都显式控制小数位数,和SQL的
DECIMAL(18,5)精度完全匹配
内容的提问来源于stack exchange,提问作者RODRIGO FIGUEIRA
相关产品推荐
相关产品推荐

