C#中的四舍五入有多坑

原文:C#中Math.Round()实现中国式四舍五入

  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 dint 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));

        }
    }
}

 

 

 

posted @ 2018-05-28 14:55  wenglabs  阅读(886)  评论(0编辑  收藏  举报