C#中的Math.Round()并不是使用的"四舍五入"法。其实在VB、VBScript、C#、J#、T-SQL中Round函数都是采用Banker's rounding(银行家算法),即:四舍六入五成双。事实上这也是IEEE的规范,因此所有符合IEEE标准的语言都应该采用这样的算法。
Math.Round(0.4) //result:0 Math.Round(0.6) //result:1 Math.Round(0.5) //result:0 Math.Round(1.5) //result:2 Math.Round(2.5) //result:2 Math.Round(3.5) //result:4 Math.Round(5.5) //result:6 Math.Round(6.5) //result:6 Math.Round(8.5) //result:8 Math.Round(9.5) //result:10
.NET 2.0 开始,Math.Round 方法提供了一个枚举选项 MidpointRounding.AwayFromZero 可以用来实现传统意义上的"四舍五入"。即: Math.Round(4.5, MidpointRounding.AwayFromZero) = 5。
但是MidpointRounding.AwayFromZero悲剧的是,如果用这个计算小数的话,就不灵了!!!
必须用这个重载方法,decimal Round(decimal d, int decimals, MidpointRounding mode)
这样计算出来的小数才是真正的中国式四舍五入!
DEMO
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TEST { class Program { static void Main(string[] args) { double x, y,z; x= 256.585; y = 255.50; z = 126854.21; Console.WriteLine("ORI {0} OUT:{1}", x, Math.Round((decimal)x, 2, MidpointRounding.AwayFromZero)); // 256.59 Console.WriteLine("ORI {0} OUT:{1} ( NO MidpointRounding.AwayFromZero PARA 【ERROR】)", x, Math.Round((decimal)x, 2)); // 256.58 【ERROR】 Console.WriteLine("---------------( From 0.01 ~ 0.09)-----------------------"); for (int i = 0; i < 10; i++) { Console.WriteLine("ORI {0:F2} OUT:{1:F2}", y, Math.Round((decimal)y, 1, MidpointRounding.AwayFromZero)); y += 0.01; } Console.WriteLine("---------------( NO MidpointRounding.AwayFromZero PARA 【ERROR】, From 0.01 ~ 0.09 )-----------------------"); for (int i = 0; i < 10; i++) { Console.WriteLine("ORI {0:F2} OUT:{1:f2}", y, Math.Round((decimal)y, 1)); y += 0.01; } Console.WriteLine(" ORI {0} OUT:{1}", x, x.ToString("f2")); Console.WriteLine("ORI {0} OUT:{1}", x, x.ToString("#0.00")); Console.WriteLine("DECIMAL ROUND, ORI {0},OUT {1}", x, decimal.Round((decimal)x, 2, MidpointRounding.AwayFromZero)); Console.WriteLine("STRING Format ORI {0},OUT {1}", x, string.Format("{0:N2}",x)); } } }