BigDecimal避坑指南

BigDecimal避坑指南
在数据使用过程中会涉及到的精度丢失各种小坑情况。
1、通常在性能测试过程中我们对返回报文的数据精度关注度不是很高。当我们在返回报文看到精度丢失时,已经是一个很大的功能缺陷了。
2、是否可以在代码走读阶段就发现并避免这种涉及到精度计算的小坑呢?这需要一定的经验积累。
文章概要梳理
BigDecimal的4个坑及如何避免:

第一:浮点类型的坑
@Test

 public void test1(){

  BigDecimal a = new BigDecimal(0.01);

  BigDecimal b = BigDecimal.valueOf(0.01);

  System.out.println("a = " + a);

  System.out.println("b = " + b);

 }
a = 0.01000000000000000020816681711721685132943093776702880859375
b = 0.01
基本结论
1、,在使用BigDecimal构造函数时,尽量传递字符串而非浮点类型;
2,如果无法满足第一条,则可采用BigDecimal#valueOf方法来构造初始化值。
3,BigDecimal常见的构造方法BigDecimal(double)    创建一个具有参数所指定双精度值的对象。
double的构造方法,会出现上述的问题,使用时需特别留意。


第二:浮点精度的坑
@Test

 public void test2(){

  BigDecimal a = new BigDecimal(0.01);

  BigDecimal b = new BigDecimal(0.010);

  System.out.println(a.equals(b));//false

  System.out.println(a.compareTo(b));//true

 }
基本结论:通常情况,如果比较两个BigDecimal值的大小,采用其实现的compareTo方法;如果严格限制精度的比较,那么则可考虑使用equals方法。
另外,这种场景在比较0值的时候比较常见,比如比较BigDecimal("0")、BigDecimal("0.0")、BigDecimal("0.00"),此时一定要使用compareTo方法进行比较。

第三:设置精度的坑
@Test

 public void test3(){

  BigDecimal a = new BigDecimal("1.0");

  BigDecimal b = new BigDecimal("3.0");

  BigDecimal c1 = a.divide(b)
  BigDecimal c2 = a.divide(b, 2,RoundingMode.HALF_UP);
 
  System.out.println(c1 );//ArithmeticException异常!
  System.out.println(c2);//0.33

 }
 
 基本结论:在使用BigDecimal进行(所有)运算时,一定要明确指定精度和舍入模式。

第四:三种字符串输出的坑
@Test

public void test4(){

    BigDecimal a = BigDecimal.valueOf(35634535255456719.22345634534124578902);

    System.out.println(a.toString());//3.563453525545672E+16


NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立货币格式化引用

NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用

percent.setMaximumFractionDigits(3); //百分比小数点最多3位

BigDecimal loanAmount = new BigDecimal("15000.48"); //金额

BigDecimal interestRate = new BigDecimal("0.008"); //利率

BigDecimal interest = loanAmount.multiply(interestRate); //相乘

System.out.println("金额:\t" + currency.format(loanAmount));//¥15,000.48 

System.out.println("利率:\t" + percent.format(interestRate));//0.8% 

System.out.println("利息:\t" + currency.format(interest));//¥120.00

}
基本结论:**根据数据结果展示格式不同,采用不同的字符串输出方法,通常使用比较多的方法为toPlainString()**。
根据需要选择输出模式
toPlainString():不使用任何科学计数法;
toString():在必要的时候使用科学计数法;
toEngineeringString() :在必要的时候使用工程计数法。类似于科学计数法,只不过指数的幂都是3的倍数,这样方便工程上的应用,因为在很多单位转换的时候都是10^3;


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值