C#四舍五入的正确方式Math.Round


IEEE标准

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

Math.Round的说明:

在C#中Math.Round默认实际上是用的IEEE舍入标准,不是四舍五入,而是 四舍六如五取偶

测试代码:

C# 全选
using System;
using System.Text;

namespace MathTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            StringBuilder sb3 = new StringBuilder();
            StringBuilder sb4 = new StringBuilder();

            for (int i = 0; i < 10; i++)
            {
                decimal v0 = (decimal)(0 + (i * 1.0 / 10));
                decimal v1 = (decimal)(1 + (i * 1.0 / 10));
                decimal v2 = (decimal)(2 + (i * 1.0 / 10));
                decimal v3 = (decimal)(3 + (i * 1.0 / 10));
                decimal v4 = (decimal)(4 + (i * 1.0 / 10));
                decimal v5 = (decimal)(5 + (i * 1.0 / 10));
                decimal v6 = (decimal)(6 + (i * 1.0 / 10));
                decimal v7 = (decimal)(7 + (i * 1.0 / 10));
                decimal v8 = (decimal)(8 + (i * 1.0 / 10));
                decimal v9 = (decimal)(9 + (i * 1.0 / 10));
                sb1.AppendLine($"{WriteVal(v0)} {WriteVal(v1)} {WriteVal(v2)} {WriteVal(v3)} {WriteVal(v4)}");
                sb2.AppendLine($"{WriteVal(v5)} {WriteVal(v6)} {WriteVal(v7)} {WriteVal(v8)} {WriteVal(v9)}");

                v0 = v0 / 10 + 1;
                v1 = v1 / 10 + 1;
                v2 = v2 / 10 + 1;
                v3 = v3 / 10 + 1;
                v4 = v4 / 10 + 1;
                v5 = v5 / 10 + 1;
                v6 = v6 / 10 + 1;
                v7 = v7 / 10 + 1;
                v8 = v8 / 10 + 1;
                v9 = v9 / 10 + 1;

                sb3.AppendLine($"{WriteVal(v0, 1)} {WriteVal(v1, 1)} {WriteVal(v2, 1)} {WriteVal(v3, 1)} {WriteVal(v4, 1)}");
                sb4.AppendLine($"{WriteVal(v5, 1)} {WriteVal(v6, 1)} {WriteVal(v7, 1)} {WriteVal(v8, 1)} {WriteVal(v9, 1)}");

            }

            Console.WriteLine(sb1.ToString());
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(sb2.ToString());
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(sb3.ToString());
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(sb4.ToString());




            Console.ReadKey();
        }

        static string WriteVal(decimal val, int digits = 0)
        {
            var str = $"Math.Round({val})={Math.Round(val, digits)}";
            return str.PadRight(23, ' ');
        }
    }
}

C#四舍五入的正确方式Math.Round

Math.Round策略枚举

好在Math.Round中有一个重载

C# 全选
public static decimal Round(decimal d, int decimals, MidpointRounding mode)

MidpointRounding 枚举 指定数学舍入方法应用于舍入数字的策略。

AwayFromZero1

舍入到最接近的数字的策略,当数字在两个数字之间的中间时,它将舍入到离零的最接近的数字。

ToEven0

舍入到最接近的数字的策略,当数字在两个数字之间的中间时,它将舍入到最接近的偶数。

ToNegativeInfinity3

向下定向舍入的策略,结果最接近且不大于无限精确结果。

ToPositiveInfinity4

向上定向舍入的策略,结果最接近且不小于无限精确结果。

ToZero2

定向向零舍入的策略,结果最接近且数量级不大于无限精确结果。

舍入到最接近

字段:

舍入到最接近的操作采用具有隐式或指定精度的原始数字;检查下一位数字,该数字的精度为 1;并返回与原始数字相同的最接近的数字。 对于正数,如果下一位数字从 0 到 4,则最接近的数字为负无穷大。 如果下一位数字从 6 到 9,则最接近的数字是正无穷大。 对于负数,如果下一个数字从 0 到 4,则最接近的数字为正无穷大。 如果下一位数字从 6 到 9,则最接近的数字为负无穷大。

如果下一位数字从 0 到 4 或 6 到 9,则 MidpointRounding.AwayFromZero 不会影响 MidpointRounding.ToEven 舍入操作的结果。 但是,如果下一位数字为 5,这是两个可能结果之间的中点,并且所有剩余的数字均为零或没有剩余数字,则最接近的数字不明确。 在这种情况下,通过舍入到最接近的模式 MidpointRounding ,可以指定舍入操作是返回最接近的从零还是最接近的偶数。

下表演示了将一些负数和正数舍入的结果以及舍入到最接近的模式。 用于对数字进行舍入的精度为零,这意味着小数点后的数字会影响舍入运算。 例如,对于数字 -2.5,小数点后面的数字为 5。 由于该数字是中点,因此可以使用值 MidpointRounding 来确定舍入结果。 如果 AwayFromZero 指定,则返回 -3,因为它是离零最近的数字,精度为零。 如果 ToEven 指定,则返回 -2,因为它是精度为零的最接近偶数。

原始数字AwayFromZeroToEven
3.544
2.833
2.532
2.122
-2.1-2-2
-2.5-3-2
-2.8-3-3
-3.5-4-4

定向舍入

字段:

定向舍入运算采用具有隐式或指定精度的原始数字,并在与原始数字相同的特定方向返回下一个最接近的数字。 控制 MidpointRounding 执行舍入的预定义编号的定向模式。

下表演示了将一些负数和正数舍入与定向舍入模式的结果。 用于舍入数字的精度为零,这意味着小数点前的数字受舍入运算的影响。

原始数字ToNegativeInfinityToPositiveInfinityToZero
3.5343
2.8232
2.5232
2.1232
-2.1-3-2-2
-2.5-3-2-2
-2.8-3-2-2
-3.5-4-3-3

Math.Round四舍五入的正确方式

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

C# 全选
Math.Round(3.45, 1, MidpointRounding.AwayFromZero)  // 3.5
Math.Round(-3.45, 1, MidpointRounding.AwayFromZero)  // -3.5

 

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
张国生
上一篇:C#计算两个日期之间的整月
下一篇:ag-grid本地js引用 下载地址
评论列表

发表评论

评论内容
昵称:
关联文章

C#四舍五入正确方式Math.Round
.NET Core中鉴权授权正确方式(.NET5)
C# 解析加载读取XML文件正确姿势
RestSharp请求https添加Cookie信息正确姿势
ASP.NET Core 中读取Post Request.Body 正确姿势
获取URL参数几种方式
win11删除快捷方式箭头
.NET C#教程初级篇 1-1 基本数据类型及其存储方式
JocPlanTask 以服务方式运行任务计划
Python爬虫解析网页提取html信息常用方式
System.BadImageFormatException:“未能加载文件或程序集 或它某一个依赖项。试图加载格式不正确程序
vue 路由跳转几种方式(带参数)
C# CefSharp使用
了解C#Expression
C#进化——C#发展史、C#1.0-10.0语法系统性梳理、C#与JAVA对比
C#图片处理
C# 金额转换,金额数字转换人民币大写
dotnet OpenXML 聊聊文本段落对齐方式
《步步入门》.NET6在Linux下以守护进程方式运行
C# 值得永久收藏WPF项目实战(经典)

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码