【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 == )
{
return (value >= ? decimal.Ceiling(value) : decimal.Floor(value));
} decimal multiple = Convert.ToDecimal(Math.Pow(, digits));
return (value >= ? decimal.Ceiling(value * multiple) : decimal.Floor(value * multiple)) / multiple;
} /// <summary>
/// 靠近 0 向下舍入
/// </summary>
public static decimal RoundDown(this decimal value, sbyte digits)
{
if (digits == )
{
return (value >= ? decimal.Floor(value) : decimal.Ceiling(value));
} decimal multiple = Convert.ToDecimal(Math.Pow(, digits));
return (value >= ? decimal.Floor(value * multiple) : decimal.Ceiling(value * multiple)) / multiple;
} /// <summary>
/// 四舍五入
/// </summary>
public static decimal RoundEx(this decimal value, sbyte digits)
{
if (digits >= )
{
return decimal.Round(value, digits, MidpointRounding.AwayFromZero);
} decimal multiple = Convert.ToDecimal(Math.Pow(, -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));
}
}
- 文毕 -
【C#】Excel舍入函数Round、RoundUp、RoundDown的C#版的更多相关文章
- Excel—数学函数
ROUND(四舍五入函数)就是说把一个小数点后多位的数四舍五入小数点位数的函数 函数语法:ROUND(哪个数,要四舍五入到小数点后几位) ROUNDUP(保留小数点几位后进位的函数)就是说要保留一个小 ...
- 浅谈Excel开发:五 Excel RTD函数
上文介绍了Excel中的UDF函数,本文介绍一下同样重要的RTD函数.从Excel 2002开始,Excel引入了一种新的查看和更新实时数据的机制,即real-time data简称RTD函数 ...
- 浅谈Excel开发:四 Excel 自定义函数
我们知道,Excel中有很多内置的函数,比如求和,求平均,字符串操作函数,金融函数等等.在有些时候,结合业务要求,这些函数可能不能满足我们的需求,比如我想要一个函数能够从WebService上获取某只 ...
- C#操作Excel的函数
对于Excel的数据处理功能,大家都已经了解. 我们经常需要将数据导入到Excel,或直接打开Excel文档,读写文件操作,这需要用到ExcelHelper类,有了这个类,这些操作大大的减少我们工作量 ...
- Excel常用函数大全
1.ABS函数 函数名称:ABS 主要功能:求出相应数字的绝对值. 使用格式:ABS(number) 参数说明:number代表需要求绝对值的数值或引用的单元格. 应用举例:如果在B2单元格 ...
- Excel REPT函数使用
需要制作1K大小的数据 使用Excel REPT函数可以迅速制造 Excel REPT 函数 =REPT(1,1024) 结果直接黏贴进txt文件,注意删除尾空格.
- Excel 自定义函数
浅谈Excel开发:四 Excel 自定义函数 我们知道,Excel中有很多内置的函数,比如求和,求平均,字符串操作函数,金融函数等等.在有些时候,结合业务要求,这些函数可能不能满足我们的需求,比 ...
- Excel里函数中的万金油,你确定不要点进来看看?
Excel里函数中的万金油,你确定不要点进来看看? 来源:EXCELHome Excel里有个号称"万能"的函数组合,这个函数组合就是INDEX+SMALL+IF,很多应用场合都能 ...
- Excel IF函数怎么用
本例主要介绍Excel表格中IF函数的用法,包括基本用法.单条件.多条件表达及在数组函数中的用法和在数组函数中怎么表达多条件和单条件. 工具/原料 Excel IF函数语法介绍: 1 IF函数 ...
随机推荐
- js模版引擎handlebars.js实用教程——with-终极this应用
返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...
- Java的一个高性能快速深拷贝方法。Cloneable?
本人在设计数据库缓存层的时候,需要对数据进行深拷贝,这样用户操作的数据对象就是不共享的. 这个思路实际上和Erlang类似,就是用数据不共享解决并发问题. 1. 序列化? 原来的做法,是用序列化,我用 ...
- ASP.NET Core: 全新的ASP.NET !
背景 最新版本的 ASP.NET 叫做 ASP.NET Core (也被称为 ASP.NET 5) 它颠覆了过去的 ASP.NET. 什么是 ASP.NET Core? ASP.NET Core ...
- sizeof && strlen 的区别
本文主要记录了 sizeof 操作符 和 strlen() 函数的区别,以及各自的用途.(在下才疏学浅,发现错误,还请留言指正) sizeof 和 strlen 的区别 示例代码如下: #includ ...
- 当pageIndex遇上pageNo
我们的项目程序里,由于赶项目进度,同时,大家缺乏相应的沟通,在服务层提供的接口里,涉及到分页查询的,有如下三种情形: l List<OrderInfo> GetOrderList(Ord ...
- iOS UITableView行高自行扩展
myTableView.estimatedRowHeight = ; myTableView.rowHeight = UITableViewAutomaticDimension; 不需要实现 - (C ...
- 关于python的最大递归层数详解
在阅读http://www.cnblogs.com/skabyy/p/3451780.html这篇文章的时候,实验yield的流式迭代素数的时候发现有个问题,故详细记录下来. 首先来看看python默 ...
- 学习ASP.NET MVC(四)——我的第一个ASP.NET MVC 实体对象
今天我将根据数据库中的表结构添加一些类.这些类将成为这个ASP.NET MVC应用程序中“模型”的一部分. 我们使用Entity Framework(实体框架)来定义和使用这些模型类,并且 ...
- css3使用box-sizing布局
css3增添了盒模型box-sizing,属性值有下面三个: content-box:默认值,让元素维持W3C的标准盒模型.元素的宽度/高度(width/height)(所占空间)等于元素边框宽度(b ...
- 快速入门系列--TSQL-01基础概念
作为一名程序员,对于SQL的使用算是基础中的基础,虽然也写了很多年的SQL,但常常还是记不清一些常见的命令,故而通过一篇博文巩固相关的记忆,并把T-SQL本身的一些新特性再进行一次学习. 首先回顾基础 ...