目录

  • BigDecimal简介
  • BigDecimal常用方法
  • 创建BigDecimal
  • 加减乘除
  • 大小比较
  • BigDecimal等值比较问题
  • 保留小数位数


BigDecimal简介

  1. 浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能用 equals 来判断。
  2. BigDecimal 可以实现对浮点数的运算,不会造成精度丢失;
  3. 通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal 来做的;

BigDecimal常用方法

创建BigDecimal

  1. 禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象,因为其存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。
  2. 在使用 BigDecimal 时,为了防止精度丢失,推荐使用BigDecimal(String val)构造方法或者 BigDecimal.valueOf(double val) 静态方法来创建对象;
如:BigDecimal g = new BigDecimal(0.1),实际存储为0.1000000000000000055511151231257827021181583404541015625
 推荐入参为String的构造方法,或BigDecimal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double实际能表达的精度对尾数进行了截断。
 BigDecimal b1 = new BigDecimal(“0.1”);
 BigDecimal b2 = BigDecimal.valueOf(0.1);

加减乘除

  • add方法用于将两个BigDecimal对象相加;
  • subtract方法用于将两个BigDecimal对象相减;
  • multiply方法用于将两个BigDecimal对象相乘;
  • divide方法用于将两个BigDecimal对象相除;

使用 divide 方法的时候尽量使用 3 个参数版本,并且RoundingMode 不要选择 ROUND_UNNECESSARY,否则很可能会遇到 ArithmeticException(无法除尽出现无限循环小数的时候),其中 scale 表示要保留几位小数,roundingMode 代表保留规则。

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode);

RoundingMode枚举:

  1. UP:向远离零的方向舍入。若舍入位为非零,则对舍入部分的前一位数字加1;若舍入位为零,则直接舍弃;
  2. DOWN:向接近零的方向舍入。不论舍入位是否为零,都直接舍弃;
  3. CEILING:向正无穷大的方向舍入。若 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;若为负,则舍入行为与 ROUND_DOWN 相同。即为向上取整模式;
  4. FLOOR:向负无穷大的方向舍入。若 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;若为负,则舍入行为与 ROUND_UP 相同。即为向下取整模式。
  5. HALF_UP:四舍五入。若舍入位大于等于5,则对舍入部分的前一位数字加1;若舍入位小于5,则直接舍弃。
  6. HALF_DOWN:五舍六入。若舍入位大于5,则对舍入部分的前一位数字加1;若舍入位小于等于5,则直接舍弃。
  7. HALF_EVEN:银行家舍入模式。若(舍入位大于5)或者(舍入位等于5且前一位为奇数),则对舍入部分的前一位数字加1;若(舍入位小于5)或者(舍入位等于5且前一位为偶数),则直接舍弃;
  8. UNNECESSARY:不舍位, 精度位数小于小数位数会抛出ArithmeticException;

大小比较

a.compareTo(b) : 返回 -1 表示 a 小于 b,0 表示 a 等于 b , 1 表示 a 大于 b。

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.compareTo(b));// 1

BigDecimal等值比较问题

BigDecimal的等值比较应使用compareTo(),而不是equals(),因为equals()会比较值和精度(1.0与1.00返回结果为false),而compareTo()会忽略精度。

BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("1.0");
System.out.println(a.equals(b));//false
System.out.println(a.compareTo(b));//0

保留小数位数

setScale()方法设置保留几位小数以及保留规则。

BigDecimal m = new BigDecimal("1.255433");
BigDecimal n = m.setScale(3,RoundingMode.HALF_DOWN);
System.out.println(n);// 1.255