一、分析
在许多数学计算的场景中,会用到近似取值的计算方法。常用的近似取值有四舍五入。
但是在某些金融行业或特殊场景中,四舍五入的方式就不太适宜。目前Java支持一下其中舍入方式:
-
ROUND_UP:远离零方向舍入,向远离0的方向舍入,也就是说,向绝对值最大的方向舍入,只要舍弃位非0即进位。
-
ROUND_DOWN:趋向零方向的舍入,向0方向靠拢,也就是说,向绝对值最小的方向输入。注意,所有的位都舍弃不存在进位的情况。
-
ROUND_CEILING:向正无穷方向舍入,向正最大方向靠拢,如果是正数,舍入行为类似于ROUND_UP;如果是负数,则舍入行为类似于ROUND_DOWN。注意,Math.round方法使用的即此模式。
-
ROUND_FLOOR:向负无穷方向舍入,向负无穷方向靠拢,如果是正数,则舍入行为类似于ROUND_DOWN;如果是负数,则舍入行为类似于ROUND_UP。
-
HALF_UP:最近数字舍入(5进),这就是我们最经典的四舍五入模式。
-
HALF_DOWN:最近数字舍入(5舍),在四舍五入中,5是进位的,而在HALF_DOWN中却是舍弃不进位。
-
HALF_EVEN:银行家算法,四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。
二、场景
使用Math.round来指定精度的整数或小数:
由于Math.round采用的舍入规则是正无穷方向舍入。所以输出结果为:
10.5近似值:11
-10.5近似值:-10
但是在银行计算利息的场景下,适应四舍五入计算利息就会出现如下情况:
按照概率计算克制,被舍入的数字均匀的分布在0到9之间,下面以10笔存款利息计算作为模型,以银行家的身份来思考这个算法:
-
四舍:舍弃的数值:0.000、0.001、0.002、0.003、0.004,因为是舍弃的,对于银行家来说,就不用付给储户利息了,那每舍弃一个数字就会赚取相应的金额:0.000、0.001、0.002、0.003、0.004。
-
五入:进位的数值:0.005、0.006、0.007、0.008、0.009,因为是进位,对于银行家来说,每进一位就会多付款给储户,也就是亏损了,那亏损的部分就是对应的10进制补数:0.005、0.004、0.003、0.002、0.001。
因为舍弃和进位的数字在0到9之间是均匀分布的,所以对于银行家来说,每10笔存款利息因采用四舍五入而获得的盈利是:
0.000+0.001+0.002+0.003+0.004-0.005-0.004-0.003-0.002-0.001=-0.005。
也就是说没10笔利息的计算中,就损失了0.005元,每笔利息计算损失0.0005元。对于一家银行(上亿储户)来说,这个误差造成的损失也不可小视觉。
这个误差是由美国的银行家发现的,所以提供出了一个修正算法,叫做银行家舍入的近似算法,其规则如下:
-
舍去的位数小于5时,直接舍去;
-
舍去的位数大于等于6时,进位后舍去;
-
当舍去的数值等于5时,分两种情况:
-
5后面还有其它数字(非0),则进位后舍去;
-
若5后面是0(即5是最后一个数字),则根据5前一位数的奇偶性来判断是否需要进位,奇数进位,偶数舍去。
-
以上规则汇总成一句话:四舍六入考虑五,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。
在Java5以上的版本中,使用银行家的舍入算法非常简单,直接使用RoundingMode类,提供Round模式即可,示例代码如下:
三、建议
根据不同的场景,慎重选择不同的舍入模式,以提高项目的精准度,减少算法损失。在大量与货币数字交互的项目中,一定要选择好近似的计算模式,尽量减少因算法不同而造成的损失。
相关推荐
java代码-BigDecimal 四舍五入保留2位小数. 金额从单位分转成单位元
Java源代码:收录了比较经典的140个Java源代码程序,适合Java初学者
Java并发编程:设计原则与模式(第二版).pdf
Jockey跟其他混淆工具不同的是:它是直接对编译过程做文章,也就是在把java文件编译为class文件的过程中对代码进行混淆,混淆后的代码中包含很多JVM 指令,大家知道JVM指令是面向机器的,人类一般很难看懂!...
用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,...
用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,演示...
Java2Pas Java代码转pas代码工具,试过,很好用的东西
一个java日程管理小程序,挺不错的,供学习交流。
本源代码包括:TestJTwain.java,ScanTwice.java,DemoFrame.java,DemoADF.java,DemoFrame.java,DemoGetCapabilities.java,DemoHiddenUI.java,ImageDisplayer.java,DemoSaveJPEG.java等等一系列扫描仪功能,...
每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 Java语言基本语法 第1章 让自己的第一个Java程序跑起来 2 教学视频:19分钟 1.1 想要用Java改变这个世界吗? 2 ...
Java程序员编写代码时应当遵循的一些基本规范
超市管理系统java源代码,超市管理系统java源代码,超市管理系统java源代码.
java代码统计工具,给出一个文件路径,统计出代码的总行数,注释行数,空行行数。含可运行的jar,以及源代码。 更多请访问: http://blog.csdn.net/china8848
《Java Web服务:构建与运行》通过提供混合架构概述、完整的工作代码示例以及短而精确的编译、部署和执行应用程序的指示,采用明确实用的方法来处理这些技术。你将学习如何从头开始编写Web服务以及集成现有服务到你...
扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码...
java游戏代码 很值得收藏
Java Web开发: 基于HttpServlet的用户登录网站 实例,参见博客:http://blog.csdn.net/yanzi1225627/article/details/8569950
7个Java小游戏源代码 解压密码是:yykings
用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,演示...
WinMerge(java代码比较工具),相当好用,可以用来比较两个java代码的不同的地方,在java开发过程中给你解决寻找两个同名文件不同之处的烦恼!用法简单!