C# 的四舍五入法System.Math.Round Bug

针对.NET平台中System.Math.Round方法不符合常规四舍五入规则的问题,本文介绍了一种适用于中国的自定义四舍五入算法实现,并提供了具体代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 最近因为项目需求。要精确到小数点后4位,第五位开始四舍五入。然而坑爹的是,微软的System.Math.Round方法并非真正的四舍五入。

  而是传说中的"四舍六入五成双"!也就是说,假设我要处理的数据为3.145,现在要精确到小数后第二位。System.Math.Round得到的结果为:3.14,因为第三位为5,而遇5成双。

  所以5的前一位要变成双。但是5的前一位是4,已经是双了,所以没处理。所以结果为3.144。太坑爹了。但是,在中国,这是不行的。

  在网络上找了好一阵,没找到可用的。迫于形势只能自己写一个在中国能用的四舍五入了。以下为实现代码:

View Code
        /// <summary>
        /// 自写四舍五入法
        /// </summary>
        /// <param name="sourceNum">要进行处理的数据</param>
        /// <param name="toRemainIndex">保留的小数位数</param>
        /// <returns>四舍五入后的结果</returns>
        /// <Author> frd  2011-11-2417:06</Author>
        public static decimal Round(decimal sourceNum, int toRemainIndex)
        {
            decimal result = sourceNum;
            string sourceString = sourceNum.ToString();
            //没有小数点,则返回原数据+"."+"保留小数位数个0"
            if (!sourceString.Contains("."))
            {
                result = Convert.ToDecimal(sourceString + "." + CreateZeros(toRemainIndex));
                return result;
            }
            //小数点的位数没有超过要保留的位数,则返回原数据+"保留小数位数 - 已有的小数位"个0
            if ((sourceString.Length - sourceString.IndexOf(".") - 1) <= toRemainIndex)
            {
                result = Convert.ToDecimal(sourceString + CreateZeros(toRemainIndex - (sourceString.Length - sourceString.IndexOf(".") - 1)));
                return result;
            }
            string beforeAbandon_String = string.Empty;
            beforeAbandon_String = sourceString.Substring(0, sourceString.IndexOf(".") + toRemainIndex + 1);
            //取得如3.1415926保小数点后4位(原始的,还没开始取舍),中的3.1415
            decimal beforeAbandon_Decial = Convert.ToDecimal(beforeAbandon_String);

            //如果保留小数点后N位,则判断N+1位是否大于等于5,大于,则进一,否则舍弃。
            if (int.Parse(sourceString.Substring(sourceString.IndexOf(".") + toRemainIndex + 1, 1)) >= 5)
            {
                #region 四舍五入算法说明
                //进一的方法举例 3.1415926,因为5后面的是9,所以5要进一位:如下:
                // 3.1415
                //         +
                // 0.0001
                //_________
                // 3.1416
                //保留N位时:
                // 3.14.......15
                //             +
                // 0.00.......01
                //_________
                // 3.14.......16
                #endregion
                string toAddAfterPoint = "0." + CreateZeros(toRemainIndex - 1) + "1";
                result = beforeAbandon_Decial + Convert.ToDecimal(toAddAfterPoint);
            }
            else
            {
                result = beforeAbandon_Decial;
            }
            return result;
        }


        /// <summary>
        /// 补 "0"方法.
        /// </summary>
        /// <param name="zeroCounts">生成个数.</param>
        /// <returns></returns>
        /// <Author> frd  2011-11-2511:06</Author>
        private static string CreateZeros(int zeroCounts)
        {
            string Result = string.Empty;
            if (zeroCounts == 0)
            {
                Result = "";
                return Result;
            }
            for (int i = 0; i < zeroCounts; i++)
            {
                Result += "0";
            }
            return Result;
        }

 

  效果图如下:

 

 

 

 

 

  这方法可直接用。起码在中国可以了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值