由 BigDecimal 舍入算法引发的血案:ROUND_HALF_UP 与 ROUND_UP
背景
项目里最近新增了一个 Excel 导入功能,要求:保存 Excel 展示出来的数据。
原格式如下:
你以为所见即所得吗?不不不,我们看到的数据实际上是 Excel 做了显示隐藏的功能,程序读出来的确实原始数据,比如【76.3%】这个数据,实际长这样【0.763490452069129】。
实际格式如下:
为了实现业务的需求,同时保证字符串的处理精度,我们在业务层用 BigDecimal 函数对 EasyExcel 读到的数据做了一层预处理。
预处理代码如下:
private String dataFormat_2(String num) {return new BigDecimal(num).setScale(3, BigDecimal.ROUND_UP) + "";}
问题
从 Excel 的原始数据可以看出,业务方需要我们的处理格式为:四舍五入,保留3位小数。但是,使用上述手段的实际处理却没有达到预期,因为个别数据与与其不符。比如:数据【0.763490452069129】按要求应为【0.763】,实际转换结果为【0.764】。
后来仔细查询了 BigDecimal 的官方文档,明白是用错了方法导致的,希望小伙伴们不要犯同样的错误,真正的四舍五入应该用【ROUND_HALF_UP】:
private String dataFormat_1(String num) {return new BigDecimal(num).setScale(3, BigDecimal.ROUND_HALF_UP) + "";}
两种方法的导入结果做了对比:
总结
BigDecimal 的舍位运算 setScale(scale, roundingMode)方法中:scale表示精确位数,roundingMode表示舍入模式。其中,【舍入模式】常见的模式有四种:
- ROUND_UP:进位制,不管保留数字后面是大是小(0除外)都会进位;
- ROUND_DOWN:保留设置数字,后面所有直接去除;
- ROUND_HALF_UP:根据保留数字后一位进行四舍五入( >=5 进位);
- ROUND_HALF_DOWN:根据保留数字后一位进行四舍五入(>5进位)。
// 舍位运算@Testpublic void testCarry() {BigDecimal bigNum = new BigDecimal("2.35"); //进位处理,2.31变成2.4 System.out.println("ROUND_UP:"+bigNum.setScale(1,BigDecimal.ROUND_UP)); //直接删除多余的小数位,如2.35会变成2.3 System.out.println("ROUND_DOWN:"+bigNum.setScale(1,BigDecimal.ROUND_DOWN)); //四舍五入,2.35变成2.4System.out.println("ROUND_HALF_UP:"+bigNum.setScale(1,BigDecimal.ROUND_HALF_UP));//五舍六入,2.35变成2.3System.out.println("ROUND_HALF_DOWN:"+bigNum.setScale(1,BigDecimal.ROUND_HALF_DOWN));//不建议使用的.setScale(1)方法System.out.println("setScale:"+bigNum.setScale(2));}
BigDecimal的详细用法,见博客:
Java中BigDecimal类的使用方法详解,常用最全系列!_Java Punk的博客-CSDN博客Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。对于Double类型的运算,通常使用此类处理,来有效避免精度问题。我们从以下五个功能点,来细说使用方法和注意事项:正文:基本运算注意事项:BigDecimal的加减乘除操作,其实最终返回的都是一个新的BigDecimal对象,因为BigDecimal都是不可变的的(BigInte...https://blog.csdn.net/weixin_44259720/article/details/87001849希望可以帮到你 ~ ~ ~
由 BigDecimal 舍入算法引发的血案:ROUND_HALF_UP 与 ROUND_UP相关推荐
- 线上 CPU100% 异常案例:一个正则表达式引发的血案
前几天线上一个项目监控信息突然报告异常,上到机器上后查看相关资源的使用情况,发现 CPU 利用率将近 100%.通过 Java 自带的线程 Dump 工具,我们导出了出问题的堆栈信息. 我们可以看到所 ...
- 一条SQL引发的“血案”:与SQL优化相关的4个案例
导读:笔者早年间从事了多年开发工作,后因个人兴趣转做数据库.在长期的工作实践中,看到了数据库工作(特别是SQL优化)面临的种种问题.本文通过几个案例探讨一下SQL优化的相关问题. 作者:马立和 高振娇 ...
- 转:一个Sqrt函数引发的血案
转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/1844725.html 源码下载地址:http://diducoder.com/sotr ...
- 一个Sqrt函数引发的血案
我们平时经常会有一些数据运算的操作,需要调用sqrt,exp,abs等函数,那么时候你有没有想过:这个些函数系统是如何实现的?就拿最常用的sqrt函数来说吧,系统怎么来实现这个经常调用的函数呢? 虽然 ...
- BigDecimal舍入模式(Rounding Modes)
BigDecimal舍入模式(Rounding Modes) 1.ROUND_UP(向上舍入) 2.ROUND_DOWN(向下舍入) 3.ROUND_CEILING(以数轴向右舍入) 4.ROUND_ ...
- 波涛汹涌的黄金甲,一碗中药引发的血案!
严重声明:网路转载 主要情节: 父王(周润发)说母后(巩利)身体虚寒,需要每天定时服用亲自配置的中药,已服用了几十年.而父王早就知道了母后和太子元祥(刘烨)之间的苟且之事,远征回宫后在其中药中加入一味 ...
- mysql backlog_一次优化引发的血案
前些天一个Nginx+PHP项目上线后遭遇了性能问题,于是打算练练手,因为代码并不是我亲自写的,所以决定从系统层面入手看看能否做一些粗线条的优化. 首先,我发现服务的Backlog设置过小,可以通过s ...
- 第三方账号登陆的过程及由此引发的血案
72agency · 2014/03/19 10:40 0x00 前言 第三方账号登陆也就是当你没有A网站的注册账号时,你可以使用该与A网站合作的第三方账号登陆A,在大多数情况下你会立即拥有与你第三方 ...
- 一个普通ERROR 1135 (HY000)错误引发的血案:
一个普通ERROR 1135 (HY000)错误引发的血案: 今天接到测试人员反应,测试环境前端应用程序无连接mysql数据库,登录mysql服务器,查看错误日志,发现有如下报错: 点击(此处)折叠或 ...
最新文章
- Xamarin+vs2010部署错误:error MSB6004: 指定的任务可执行文件位置\sdk\\tools\zipalign.exe”无效...
- ML之Clustering之H-clustering:Hierarchical clustering算法相关论文、主要思路、关键步骤、代码实现等相关配图之详细攻略
- 在服务器上用Fiddler抓取HTTPS流量
- 今天正式开通51CTO技术博客
- 1.2 Coin 项目
- 从零开始学架构2 - 高性能篇
- 彻底解决springboot修改页面和代码会自动重启
- 限制内核printk的打印频率
- CentOS 大量的TIME_WAIT解决方法
- 列表推导式 生成器表达式
- 【Iftop】实时监控流量工具
- 按键精灵 手机 oracle,按键精灵Android版:软件使用
- 给大家拓宽点边界,15分钟带你入门sklearn与机器学习——分类算法篇
- 如何免费使用xshell、xftp工具
- Compose 跨平台的现状
- 11对战平台服务器维护,11对战平台无法进入游戏【解决方法】
- dell 730xd硬raid配置
- 解决:HotSeat短信图标提醒有误
- 人一般长到几岁才会停止长高?
- 全球与中国冷冻莴苣市场深度研究分析报告
热门文章
- 设置成品物料可以进行货物移动,不可进行生产工单的创建!
- 10 分钟搭建一个超好用的 CMDB 系统
- 113 错误 mysql_ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.56.105' (113)
- connect() failed (113: No route to host)
- 大专计算机类英语翻译,专科英文(大学专科用英文怎么说)
- c语言reentrant,Keil C51對C語言的關鍵詞擴展之十五: reentrant
- 七夕送什么礼物?最好用蓝牙耳机排行
- 飒,京准NTP校时服务器产品配置步骤
- 弘辽科技:看了这些,你就知道为什么你的淘宝店铺做不起来
- jquery html() ie兼容,ie是否支持jquery