宝塔山 发表于 2023-8-11 13:20:16

C#中四舍五入的正确写法是什么?

概述:就在今天,测试提一个BUG,是什么呢?就是在计算商品采购价时,需要保留2位小数,当时是使用【Math.Round(采购价,2)】这种方法进行四舍五入的,但是这样写会有问题,至于什么问题呢,来看看这篇文章就对了!

四舍五入是一种精确度的计数保留法。在取小数近似数的时候,如果尾数的最高位数字是4或者比4小,就把尾数去掉。如果尾数的最高位数是5或者比5大,就把尾数舍去并且在它的前一位进"1",这种取近似数的方法叫做四舍五入法。

一、BUG回顾

我们经常使用四舍五入时,会使用【Math.Round(价格,2)】这种方法进行转换。而我也不例外,在计算价格时也是使用这个方法,而当遇到类似这样的数值时【301.505 】,返回的值却是【301.5】,按照四舍五入的原则,应该返回【301.51】才对是吧。


代码:
https://cdn.nlark.com/yuque/0/2023/png/1183442/1691724801300-64fb4e6c-3337-401b-bddd-afaa92e0458d.png#averageHue=%23fcf9f7&clientId=u968c7205-b729-4&from=paste&height=175&id=u0ebe4acd&originHeight=175&originWidth=407&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17095&status=done&style=none&taskId=ud676c950-3ba1-4202-91d1-a5938ff53ee&title=&width=407
效果:
https://cdn.nlark.com/yuque/0/2023/png/1183442/1691724772842-e028bdd7-9510-4932-ad0f-51e791ea5e3e.png#averageHue=%23302f2f&clientId=u968c7205-b729-4&from=paste&height=316&id=u391b17e8&originHeight=316&originWidth=500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8701&status=done&style=none&taskId=u5ccd992d-71f5-4efb-8187-67745cf27bc&title=&width=500
源码:
static void Main(string[] args)
      {
            double price = 320.75 * 0.94;

            Console.WriteLine(price);//301.505
            Console.WriteLine(Math.Round(price, 2));//301.5

            Console.ReadKey();
      }
那这是为什么呢?根据引用ChatGPT回答如下:
在C#中,Math.Round()函数默认使用的是银行家舍入法(Banker's rounding),即当小数部分为5时,会根据前一位数字的奇偶性来决定舍入方式。因此,1.085经过Math.Round(301.505,2)舍入后的返回值是301.5,而不是301.51.

然后四舍五入也有个国际惯例,叫奇进偶舍 。就是当舍入位前面一位是奇数时就进,为偶数时就舍。但是这种转换在国内很多企业就行不通了,那如何解决呢?请看下面方法。

二、解决掉BUG

我们可以这样写【Math.Round(价格, 2, MidpointRounding.AwayFromZero)】就可以解决啦。官方是这样描述的:"当一个数字是其他两个数字的中间值时,会将其舍入为两个值中绝对值较小的值"。
代码:
https://cdn.nlark.com/yuque/0/2023/png/1183442/1691725495510-e15a6d26-5dc4-4075-8395-7d46e5d6a9d3.png#averageHue=%23fdfaf8&clientId=u968c7205-b729-4&from=paste&height=184&id=u6783856f&originHeight=184&originWidth=536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=23537&status=done&style=none&taskId=u71fd5ab1-c10d-446a-88b4-aea16c5f462&title=&width=536
效果:
https://cdn.nlark.com/yuque/0/2023/png/1183442/1691725538704-7debad1b-e216-4134-9248-ca1f363c1860.png#averageHue=%23302d2d&clientId=u968c7205-b729-4&from=paste&height=350&id=u92fa4dca&originHeight=350&originWidth=587&originalType=binary&ratio=1&rotation=0&showTitle=false&size=14271&status=done&style=none&taskId=uc017ab3b-d7e6-4ae6-b514-28da7aa3af3&title=&width=587
源码:
      static void Main(string[] args)
      {
            double price = 320.75 * 0.94;

            Console.WriteLine(price);//301.505
            Console.WriteLine(Math.Round(price, 2));//301.5

            double res = Math.Round(price, 2, MidpointRounding.AwayFromZero);
            Console.WriteLine(res);///301.51

            Console.ReadKey();
      }
三、封装方法

为了能快速使用,为此封装了一个公共方法。


封装代码:
/// <summary>
    /// Math辅助类
    /// </summary>
    public static class MathHelper
    {
      /// <summary>
      /// 四舍五入
      /// </summary>
      /// <param name="value">值</param>
      /// <param name="digits">保留的小数位数(默认:2位)</param>
      /// <returns></returns>
      public static double MathHalfAdjust(double value, int digits = 2)
      {
            return Math.Round(value, digits, MidpointRounding.AwayFromZero);
      }
    }
调用实例:
MathHelper.MathHalfAdjust(12.105, 2);//使用原文链接:https://www.cnblogs.com/kimiliucn/p/17622687.html

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: C#中四舍五入的正确写法是什么?