【C#】Excel舍入函数Round、RoundUp、RoundDown的C#版

原文:【C#】Excel舍入函数Round、RoundUp、RoundDown的C#版

本人在C#中进行小数舍入的时候常常会怀念Excel中的Round、RoundUp、RoundDown这几个函数,原因就是后者“接地气”,比较符合俺小老百姓的舍入要求,啥“银行家舍入法”就让银行家用去吧。今儿有空,就把它实现了一下,先温习一下这几个Excel函数的功能:

Round(value, digits)

将value按四舍五入法进行舍入,保留digits位小数;当digits为负时,在小数点左侧进行舍入;当value为负时,表现与正数完全相反。

举例:Round(3.145, 2) = 3.15;Round(-3.145, 2) = -3.15;Round(3145, -2) = 3100

RoundUp(value, digits)

按远离 0 的方向,将value向上舍入,保留digits位小数;当digits为负时,在小数点左侧进行舍入

举例:RoundUp(3.111, 2) = 3.12;RoundUp(-3.111, 2) = -3.12;RoundUp(3111, -2) = 3200

RoundDown(value, digits)

按靠近 0 的方向,将value向下舍入,保留digits位小数;当digits为负时,在小数点左侧进行舍入

举例:RoundDown(3.145, 2) = 3.14;RoundDown(-3.145, 2) = -3.14;RoundDown(3145, -2) = 3100

实现原理:

- 对于RoundUp和RoundDown,由于decimal或Math类的Ceiling和Floor方法(下称C/F)只能取整,所以先根据要保留的位数,乘除得到可供C/F方法发挥的新值,然后就可以利用C/F得到舍入后的值,再乘/除回去,得到最终结果。此法市面常见。

举例:1.114向上保留2位,首先1.114x100得到111.4,再用C(111.4)得到112,然后112 / 100,最终得到1.12

问题:由于要先对原值进行乘除,所以对于接近Max/Min、或精度过高的原值,这一步就会造成溢出,所以Up和Down不能应对特别大的值,但日常应用相信没问题。

- 对于RoundEx方法,则直接封装decimal.Round(decimal, MidpointRounding.AwayFromZero)得到结果。

实现说明:

- 以扩展方法提供,兼容常规方法调用方式(废话)。即可以3.145M.RoundEx(2),也可以MathEx.RoundEx(3.145M, 2)

- 每个方法以decimal和double两种类型提供重载,共6个方法

- 以decimal类型为基础进行实现,double版只是重用+类型转换。之所以不对double进行实现,不是因为偷懒,而是因为浮点运算容易扯蛋,如555.55x100=55554.999999999993。关于浮点运算的不可靠性,可参看:http://www.cnblogs.com/ethancai/articles/1237012.html

- 四舍五入函数命名为RoundEx是因为decimal类已经存在一个叫Round的静态方法,如果不错开,将不能以扩展方式3M.Round()进行调用。而且虽然.net在命名上具有极大的包容度,但我认为还是尽量避开FCL命名的好,无谓去“享受”这种自由度

- 几个方法之所以都要先判断一下保留位数,而没有直接使用10的digits次方进行运算,是想尽量沿用decimal类型的原生方法,减少没必要的数学运算。咱追求的不是极简的代码,而是性能。当然,没测试过~鸡蛋飞来中...

废话了一堆,上代码:

/// <summary>
/// 数学类扩展方法
/// </summary>
public static class MathEx
{
    /// <summary>
    /// 远离 0 向上舍入
    /// </summary>
    public static decimal RoundUp(this decimal value, sbyte digits)
    {
        if (digits == 0)
        {
            return (value >= 0 ? decimal.Ceiling(value) : decimal.Floor(value));
        }

        decimal multiple = Convert.ToDecimal(Math.Pow(10, digits));
        return (value >= 0 ? decimal.Ceiling(value * multiple) : decimal.Floor(value * multiple)) / multiple;
    }

    /// <summary>
    /// 靠近 0 向下舍入
    /// </summary>
    public static decimal RoundDown(this decimal value, sbyte digits)
    {
        if (digits == 0)
        {
            return (value >= 0 ? decimal.Floor(value) : decimal.Ceiling(value));
        }

        decimal multiple = Convert.ToDecimal(Math.Pow(10, digits));
        return (value >= 0 ? decimal.Floor(value * multiple) : decimal.Ceiling(value * multiple)) / multiple;
    }

    /// <summary>
    /// 四舍五入
    /// </summary>
    public static decimal RoundEx(this decimal value, sbyte digits)
    {
        if (digits >= 0)
        {
            return decimal.Round(value, digits, MidpointRounding.AwayFromZero);
        }

        decimal multiple = Convert.ToDecimal(Math.Pow(10, -digits));
        return decimal.Round(value / multiple, MidpointRounding.AwayFromZero) * multiple;
    }

    /// <summary>
    /// 远离 0 向上舍入
    /// </summary>
    public static double RoundUp(this double value, sbyte digits)
    {
        return decimal.ToDouble(Convert.ToDecimal(value).RoundUp(digits));
    }

    /// <summary>
    /// 靠近 0 向下舍入
    /// </summary>
    public static double RoundDown(this double value, sbyte digits)
    {
        return decimal.ToDouble(Convert.ToDecimal(value).RoundDown(digits));
    }

    /// <summary>
    /// 四舍五入
    /// </summary>
    public static double RoundEx(this double value, sbyte digits)
    {
        return decimal.ToDouble(Convert.ToDecimal(value).RoundEx(digits));
    }
}

- 文毕 -

时间: 2024-11-08 08:35:52

【C#】Excel舍入函数Round、RoundUp、RoundDown的C#版的相关文章

EXCEL常用函数公式

1    EXCEL基本操作 1      基本概念:工作簿,工作表,行,列,单元格 2      数据录入 批量录入相同数据(ctrl+enter) ***号码输入(设置单元格属性为"文本"或者前面加 ' ) 分数输入(直接输1/3EXCEL默认为1月3日,应该写成0空格 1/3) 单元格里换行(alt+enter) 3      查找 :模糊查找.值查找 4      冻结窗口 5      筛选:一般筛选,空行筛选 6      行列转置 7      插入对象:对象格式的设置

Javascript中,数学方法可以分成以下几类: constans(常数)、power functions(乘方函数)、trigonometic functions(三角函数)、rounding functions(舍入函数)、random numbers(随机数字)

在Javascript中,数学方法可以分成以下几类: constans(常数).power functions(乘方函数).trigonometic functions(三角函数).rounding functions(舍入函数).random numbers(随机数字) 常数和乘方函数 Math.E 自然对数的底(为常数) 2.718 Math.LN10 10的自然对数 2.302 Math.LN2 2的自然对数 0.693 Math.PI 圆周率 3.1415 Math.SQRT1_2 1/

excel VLOOKUP函数的用法

VLOOKUP函数是Excel中几个最重函数之中的一个,为了方便大家学习,兰色幻想特针对VLOOKUP函数的使用和扩展应用,进行一次全面综合的说明.本文为入门部分 一.入门级 VLOOKUP是一个查找函数,给定一个查找的目标,它就能从指定的查找区域中查找返回忆要查找到的值.它的基本的语法为: VLOOKUP(查找目标,查找范围,返回值的列数,精确OR模糊查找) 以下以一个实例来介绍一下这四个參数的使用 例1:例如以下图所看到的,要求依据表二中的姓名,查找姓名所相应的年龄. 公式:B13 =VLO

MySQL四舍五入函数ROUND(x)、ROUND(x,y)和TRUNCATE(x,y)

MySQL四舍五入函数ROUND(x) ROUND(x)函数返回最接近于参数x的整数,对x值进行四舍五入. 实例: 使用ROUND(x)函数对操作数进行四舍五入操作.SQL语句如下: mysql>SELECT ROUND(-2.34),ROUND(-4.56),ROUND(2.34),ROUND(4.56); ROUND(x)函数的执行结果如下图所示: 上图中代码执行的结果显示,进行四舍五入处理以后,只保留了各个值的整数部分. MySQL四舍五入函数ROUND(x,y) ROUND(x,y)函数

Excel 自定义函数

Excel自定义函数编写有3种方法: 1.VBA种编写:直接编写 2.自定义函数编写到XLL中:如果您熟悉C++,可以将自定义函数编写到XLL中,不熟悉也可以使用ExcelDNA这个开源的库使用.NET技术也可以将您的代码编译为XLL 3.将类库注册成Com组件也可在Excel中调用:如果熟悉.NET,使用C#编写自定义函数类库,然后将类库注册成Com组件也可在Excel中调用

Delphi Excel操作,写了个ADODataSet转Excel的函数作为后期学习的例子

使用该函数需要先Use Excel2010 //DataSet导出Excel2010格式//FileName=待导出的Excel的文件名,不带路径以及后缀:TitleLine1=导出后Excel第一表头,TitleLine2=Excel第二表头:CellsNames=Excel表格中Field的Title名称://IsOpen=是否马上打开 procedure sysDSetToXlsx(DSet: TADODataSet;FileName,TitleLine1,TitleLine2:Strin

Excel REPT函数使用

需要制作1K大小的数据 使用Excel REPT函数可以迅速制造 Excel REPT 函数 =REPT(1,1024) 结果直接黏贴进txt文件,注意删除尾空格.

Excel常用函数大全

1.ABS函数  函数名称:ABS  主要功能:求出相应数字的绝对值.  使用格式:ABS(number)  参数说明:number代表需要求绝对值的数值或引用的单元格.  应用举例:如果在B2单元格中输入公式:=ABS(A2),则在A2单元格中无论输入正数(如100)还是负数(如-100),B2中均显示出正数(如100).  特别提醒:如果number参数不是数值,而是一些字符(如A等),则B2中返回错误值“#VALUE!”. 2.AND函数  函数名称:AND  主要功能:返回逻辑值:如果所

excel VLOOKUP函数的使用方法 .

VLOOKUP函数是Excel中几个最重函数之一,为了方便大家学习,兰色幻想特针对VLOOKUP函数的使用和扩展应用,进行一次全面综合的说明.本文为入门部分 一.入门级 VLOOKUP是一个查找函数,给定一个查找的目标,它就能从指定的查找区域中查找返回想要查找到的值.它的基本语法为: VLOOKUP(查找目标,查找范围,返回值的列数,精确OR模糊查找) 下面以一个实例来介绍一下这四个参数的使用 例1:如下图所示,要求根据表二中的姓名,查找姓名所对应的年龄. 公式:B13 =VLOOKUP(A13