关于DecimalFormat的取舍问题,DecimalFormat四舍五入的坑

背景

在使用DecimalFormat对数字进行格式化的时候,发现数字有时候四舍五入了,有时候又没有四舍五入,针对这个问题进行研究。

测试代码

public static void main (String[] args)
{
        DecimalFormat df=new DecimalFormat("#.#");
        double a=3.25,b=3.35;
        System.out.println(df.format(a));
        System.out.println(df.format(3.251));
        System.out.println(df.format(b));

执行结果:

3.2
3.3
3.4

问题

为什么打印结果是3.2 、3.3和3.4?DecimalFormat的取舍原则是什么?

原理

DecimalFormat 默认使用的是进位方式是RoundingMode.HALF_EVEN,此舍入模式也称为“银行家算法”,主要在美国使用。

银行家算法:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一

规律就是看进舍位的前一位是奇数还是偶数
奇数:四舍五入
偶数:五舍六入
若进舍位是5,且后面非0:进一

如3.25 保存一位小数,进舍位前一位是2,2是偶数,五舍六入 结果就是3.2,如果是3.26 结果就是3.3;
如3.251 保存一位小数,5后面非0,所以会进一,即3.3;
再如3.35 保存一位小数 进舍位前一位是3,3是奇数,四舍五入 结果就是3.4。

如果想实现四舍五入,增加下面代码,切换进位方式
df.setRoundingMode(RoundingMode.HALF_UP);

public static void main(String[] args) {
    DecimalFormat df=new DecimalFormat("#.#");
    df.setRoundingMode(RoundingMode.HALF_UP);//HALF_UP四舍五入
    double a=3.25,b=3.35;
    System.out.println(df.format(a)); //3.3
    System.out.println(df.format(3.251)); //3.3
    System.out.println(df.format(b)); //3.4
}

ps:format方法直接传float、double类型会有各种意想不到的坑,很多地方推荐使用 df.format(BigDecimal.valueOf(a)) 或 df.format(new BigDecimal(a)),但是new BigDecimal直接传入float、double类型也会出现精度缺失问题。BigDecimal.valueOf()传入float类型会出现精度问题。问题代码如下:

public static void main(String[] args) {
    double b=3.35d;
    float c = 3.33f;
    System.out.println(new BigDecimal(b)); //3.350000000000000088817841970012523233890533447265625
    System.out.println(new BigDecimal(c)); //3.3299999237060546875
    System.out.println(BigDecimal.valueOf(b)); //3.35
    System.out.println(BigDecimal.valueOf(c)); //3.3299999237060547
}

解决方法
将float、double类型转为String,然后传给BigDecimal

double b=3.35d;
float c = 3.33f;

System.out.println(new BigDecimal(String.valueOf(b))); //3.35
System.out.println(new BigDecimal(String.valueOf(c))); //3.33

BigDecimal可以单独使用,这个类也自带舍入模式设定方法。

public static String getAmount(String str){
    BigDecimal bigDecimal=new BigDecimal(str);
    return String.valueOf(bigDecimal.setScale(2,RoundingMode.HALF_UP));
}
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值