C#中四舍五入的问题

C# 中没有四舍五入函数,因为四舍五入算法不科学,国际通行的是 Banker 舍入法 Banker 's rounding(银行家舍入)算法,即四舍六入五取偶。事实上这也是 IEEE 规定的舍入标准。因此所有符合 IEEE 标准的语言都应该是采用这一算法的


起源

项目开发中,计算星星数时用到

描述

Math.Round()准确的说,这个函数不是四舍五入,而是四舍六入五凑偶,就是说小于4或大于6的该舍该入是没有争议的,而5处在正中间,如果四舍五入则会造成数据的整体偏差,所以采取的原则是:如果舍入位为5,则舍入后最后一位为偶数,这是国际惯例。

C# 中没有四舍五入函数,事实上我知道的程序语言都没有四舍五入函数,因为四舍五入算法不科学,国际通行的是 Banker 舍入法 Banker 's rounding(银行家舍入)算法,即四舍六入五取偶。事实上这也是 IEEE 规定的舍入标准。因此所有符合 IEEE 标准的语言都应该是采用这一算法的。

解决方法

public static double Round(double num, int prec)
{
    bool isNegative = false;
    //如果是负数
    if (num < 0)
    {
        isNegative = true;
        num = -num;
    }

    int IValue = 1;
    for (int i = 1; i <= prec; i++)
    {
        IValue = IValue * 10;
    }
    double Int = Math.Round(num * IValue + 0.5, 0);
    num = Int / IValue;

    if (isNegative)
    {
        num = -num;
    }

    return num;
}

解析

Math.Round 方法默认的也是 Banker 舍入法 在 .NET 2.0 中 Math.Round 方法有几个重载方法

  • Math.Round(Decimal, MidpointRounding)

  • Math.Round(Double, MidpointRounding)

  • Math.Round(Decimal, Int32, MidpointRounding)

  • Math.Round(Double, Int32, MidpointRounding)

将小数值舍入到指定精度。MidpointRounding 参数,指定当一个值正好处于另两个数中间时如何舍入这个值

该参数是个 MidpointRounding 枚举

此枚举有两个成员:

AwayFromZero 当一个数字是其他两个数字的中间值时,会将其舍入为两个值中绝对值较大的值。

ToEven 当一个数字是其他两个数字的中间值时,会将其舍入为最接近的偶数。

所以,要实现四舍五入函数,对于正数,可以加一个 MidpointRounding.AwayFromZero 参数指定当一个数字是其他两个数字的中间值时其舍入为两个值中绝对值较大的值

  • floor 直接往小的取,比如 floor(-123.55)=-124,floor(123.55)=123

  • trunc 直接切下整数,比如 trunc(-123.55)=-123, floor(123.55)=123

  • ceil 直接往大的取,比如 ceil(-123.55)=-123, ceil(123.55)=124

  • round 计算四舍五入,比如 round(-123.55)=-124,round(123.55)=124

知识共享许可协议
《C#中四舍五入的问题》 常伟华 创作。
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议 | 3.0 中国大陆许可协议进行许可。

站内公告

A PHP Error was encountered

Severity: Core Warning

Message: PHP Startup: zip: Unable to initialize module Module compiled with module API=20060613 PHP compiled with module API=20090626 These options need to match

Filename: Unknown

Line Number: 0

Backtrace: