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("\nORI {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));
}
}
}