BigDecimal的舍入方式

枚举类:RoundingMode
1、UP(BigDecimal.ROUND_UP):远离零方向舍入。向远离0的方向舍入,也就是说,向绝对值最大的方向舍入,只要舍弃位非0即进位。
2、DOWN(BigDecimal.ROUND_DOWN):趋向0方向舍入。向0方向靠拢,也就是说,向绝对值最小的方向输入,注意:所有的位都舍弃,不存在进位情况。
3、CEILING(BigDecimal.ROUND_CEILING):向正无穷方向舍入。向正最大方向靠拢,如果是正数,舍入行为类似于ROUND_UP;如果为负数,则舍入行为类似于ROUND_DOWN.注意:Math.round方法使用的即为此模式。
4、FLOOR(BigDecimal.ROUND_FLOOR):向负无穷方向舍入。向负无穷方向靠拢,如果是正数,则舍入行为类似ROUND_DOWN,如果是负数,舍入行为类似以ROUND_UP。
5、HALF_UP(BigDecimal.ROUND_HALF_UP):最近数字舍入(5舍),这就是我们经典的四舍五入。
6、HALF_DOWN(BigDecimal.ROUND_HALF_DOWN):最近数字舍入(5舍)。在四舍五入中,5是进位的,在HALF_DOWN中却是舍弃不进位。
5.5 -> 5
2.5 -> 2
1.6 -> 2
1.1 -> 1
1.0 -> 1
-1.0 -> -1
-1.1 -> -1
-1.6 -> -2
-2.5 -> -2
-5.5 -> -5
7、HALF_EVEN(BigDecimal.ROUND_HALF_EVEN):银行家算法。四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。见最后详解。
5.5 -> 6
2.5 -> 2
1.6 -> 2
1.1 -> 1
1.0 -> 1
-1.0 -> -1
-1.1 -> -1
-1.6 -> -2
-2.5 -> -2
-5.5 -> -6
8、UNNECESSARY(BigDecimal.ROUND_UNNECESSARY):断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
精确到一位小数点
1.0—>1
1.1抛异常

银行家算法:

我们知道银行的盈利渠道主要是利息差,从储户手里收拢资金,然后房贷出去,期间的利息差额便是所获得利润,对一个银行来说,对付给储户的利息计算非常频繁,人民银行规定每个季度末月的20日为银行结息日,一年有4次的结息日。

场景介绍完毕,我们回头来看看四舍五入,小于5的数字被舍去,大于5的数字进位后舍去,由于单位上的数字都是自然计算出来的,按照利率计算可知,被舍去的数字都分布在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、.0004、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千万储户的银行家来说(对国内银行来说,5千万是个小数字),每年仅仅因为四舍五入的误差而损失的金额是:

银行账户数量(5千万)*4(一年计算四次利息)*0.0005(每笔利息损失的金额)

5000*10000*0.0005*4=100000.0;即,每年因为一个算法误差就损失了10万元,事实上以上的假设条件都是非常保守的,实际情况可能损失的更多。那各位可能要说了,银行还要放贷呀,放出去这笔计算误差不就抵消了吗?不会抵消,银行的贷款数量是非常有限的其数量级根本无法和存款相比。

这个算法误差是由美国银行家发现的(那可是私人银行,钱是自己的,白白损失了可不行),并且对此提出了一个修正算法,叫做银行家舍入(Banker's Round)的近似算法,其规则如下:

  1. 舍去位的数值小于5时,直接舍去;

  2. 舍去位的数值大于等于6时,进位后舍去;

  3. 当舍去位的数值等于5时,分两种情况:5后面还有其它数字(非0),则进位后舍去;若5后面是0(即5是最后一个数字),则根据5前一位数的奇偶性来判断是否需要进位,奇数进位,偶数舍去。

以上规则汇总成一句话:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。我们举例说明,取2位精度;

round(10.5551) = 10.56 round(10.555) = 10.56 round(10.545) = 10.54

你可能感兴趣的:(java)