最近在研究java的四舍五入,其中有一个方法如下
1 | new BigDecimal(val).setScale(newScale, BigDecimal.ROUND_HALF_DOWN)); |
其中val是要处理的浮点数
newScale表示要保留小数点后几位
BigDecimal.ROUND_HALF_DOWN表示若舍弃的部分>0.5则进位,否则直接舍弃,说白了就是五舍六入
比如说1.234,保留两位小数处理结果为1.23
比如说1.235,保留两位小数处理结果为1.23
比如说1.236,保留两位小数处理结果为1.24
为了验证我的猜测,马上写几行代码验证下
1 | System.out.println(new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_HALF_DOWN)); |
发现第二条结果与我的猜测不一致,感觉有点受伤
1 | 1.23 |
1.235小数点后三位为5,明明是要舍弃的,为何进位了,难道网上的教程都是骗人
折腾了好久,最后发现原来我的写法跟网上别人的还是有细微差别
我的是:new BigDecimal(1.235).setScale(2, BigDecimal.ROUND_HALF_DOWN)
别人家的是:new BigDecimal(“1.235”).setScale(2, BigDecimal.ROUND_HALF_DOWN),这样的写法结果确实是1.23
可是为何同样的数值,传double类型不行,传String就可以?难道这两种方法初始化的BigDecimal大小不一样?打印出来发现确实不一样
1 | // 打印结果为1.2350000000000000976996261670137755572795867919921875 |
new BigDecimal(1.235)的真实值为1.2350000000000000976996261670137755572795867919921875这一长串数字,舍弃的部分是大于0.5的,所以才进位的。
所以为了避免得到错误的结果还是建议传String类型的值,如果是double类型就用如下方法先转成String再处理
1 | new BigDecimal(String.valueOf(1.235)).setScale(2, BigDecimal.ROUND_HALF_DOWN); |
还有另一种方法是直接传double类型的
1 | BigDecimal.valueOf(1.235).setScale(2, BigDecimal.ROUND_HALF_DOWN); |
查看BigDecimal.valueOf源码,其内部实现其实也是先转成String
1 | /** |
总结
用BigDecimal处理浮点数时BigDecimal的初始化最好采用如下方法
1 | double d = 1.235; |