BigDecimal笔记

创建:

BigDecimal a = new BigDecimal(0.1);
System.out.println(a);//0.1000000000000000055511151231257827021181583404541015625
System.out.println(a.doubleValue());//0.1

我们可以看到用构建方法创建时如果是数值会有精度问题,但在转换为double时又正常了;那么在操作的时候精度是否正常呢?

BigDecimal b = BigDecimal.valueOf(0.1);
System.out.println(b);//0.1
System.out.println(a.compareTo(b));//1    

如果使用valueOf()方法创建就不会出现精度问题,并且我使用compareTo()方法比较了大小,发现a比b大,所以a在操作时精度问题是存在的,所以我们尽量使用第二种方法创建。

BigDecimal c = new BigDecimal("0.1");
System.out.println(c);//0.1

如果是在构建时传入的是字符串,就不会出现精度问题。事实上第二种创建方法内部其实是调用了第三种创建方法的return new BigDecimal(Double.toString(val));把数值转换成字符串后再创建的。

 

常用方法:

加减乘除,这里要提一下,加减乘除都是有返回值的,返回结果的BigDecimal对象,而不是改变原有的操作数。

BigDecimal x;
x = b.add(c);//
System.out.println(x);//0.2
x = b.subtract(c);//
System.out.println(x);//0.0
x = b.multiply(c);//
System.out.println(x);//0.01
x = b.divide(c);//
System.out.println(x);//1
x = b.divide(BigDecimal.valueOf(0.022),2,BigDecimal.ROUND_HALF_UP);//除,保留2位小数,四舍五入
System.out.println(x);//4.55

取舍规则:

BigDecimal.ROUND_UP 绝对值向上取整;已过期,替代:RoundingMode.UP

BigDecimal y = BigDecimal.valueOf(0.1111111).setScale(2,BigDecimal.ROUND_UP);
System.out.println(y);//0.12
y = BigDecimal.valueOf(-0.1111111).setScale(2,BigDecimal.ROUND_UP);
System.out.println(y);//-0.12

BigDecimal.ROUND_DOWN 绝对值向下取整;已过期,替代:RoundingMode.DOWN

BigDecimal y = BigDecimal.valueOf(0.1111111).setScale(2,BigDecimal.ROUND_DOWN);
System.out.println(y);//0.11
y = BigDecimal.valueOf(-0.1111111).setScale(2,BigDecimal.ROUND_DOWN);
System.out.println(y);//-0.11

BigDecimal.ROUND_CEILING 向上取整;已过期,替代:RoundingMode.CEILING

BigDecimal y = BigDecimal.valueOf(0.1111111).setScale(2,BigDecimal.ROUND_CEILING);
System.out.println(y);//0.12
y = BigDecimal.valueOf(-0.1111111).setScale(2,BigDecimal.ROUND_CEILING);
System.out.println(y);//-0.11

BigDecimal.ROUND_FLOOR 向下取整;已过期,替代:RoundingMode.FLOOR

BigDecimal y = BigDecimal.valueOf(0.1111111).setScale(2,BigDecimal.ROUND_FLOOR);
System.out.println(y);//0.11
y = BigDecimal.valueOf(-0.1111111).setScale(2,BigDecimal.ROUND_FLOOR);
System.out.println(y);//-0.12

BigDecimal.ROUND_HALF_UP 四舍五入;已过期,替代:RoundingMode.HALF_UP

BigDecimal y = BigDecimal.valueOf(0.444444).setScale(2,BigDecimal.ROUND_HALF_UP);
System.out.println(y);//0.44
y = BigDecimal.valueOf(0.555555).setScale(2,BigDecimal.ROUND_HALF_UP);
System.out.println(y);//0.56

BigDecimal.ROUND_HALF_DOWN 这个比较特殊,我称之为5舍5+入,看一下例子就懂了,这里看的不只是保留位下一位的数值,而是保留位后面的所有位数值,因为0.0050000001大于0.005,所以进,而小于或等于0.005则舍弃;已过期,替代:RoundingMode.HALF_DOWN

BigDecimal y = BigDecimal.valueOf(0.555).setScale(2,BigDecimal.ROUND_HALF_DOWN);
System.out.println(y);//0.55
y = BigDecimal.valueOf(0.5550000001).setScale(2,BigDecimal.ROUND_HALF_DOWN);
System.out.println(y);//0.56

BigDecimal.ROUND_HALF_EVEN 银行家算法,四舍六入,如果为5,看看后面还有没有数,有就进位,没有则看前面一位,如果为奇数则进位,如果为偶数则舍弃;已过期,替代:RoundingMode.HALF_EVEN

BigDecimal y = BigDecimal.valueOf(0.554).setScale(2,BigDecimal.ROUND_HALF_EVEN);
System.out.println(y);//0.55
y = BigDecimal.valueOf(0.556).setScale(2,BigDecimal.ROUND_HALF_EVEN);
System.out.println(y);//0.56
y = BigDecimal.valueOf(0.555001).setScale(2,BigDecimal.ROUND_HALF_EVEN);
System.out.println(y);//0.56
y = BigDecimal.valueOf(0.515).setScale(2,BigDecimal.ROUND_HALF_EVEN);
System.out.println(y);//0.52
y = BigDecimal.valueOf(0.525).setScale(2,BigDecimal.ROUND_HALF_EVEN);
System.out.println(y);//0.52

BigDecimal.ROUND_UNNECESSARY 用于断言请求的操作具有精确结果,因此不发生舍入,说人话就是,在取舍之前我就知道不需要取舍。如果数值真的需要取舍才能达到限制的精度,就抛异常。已过期,替代:RoundingMode.UNNECESSARY

BigDecimal y = BigDecimal.valueOf(1.00).setScale(0,BigDecimal.ROUND_UNNECESSARY);
System.out.println(y);//1
y = BigDecimal.valueOf(1).divide(BigDecimal.valueOf(100),2,BigDecimal.ROUND_UNNECESSARY);
System.out.println(y);//0.01
y = BigDecimal.valueOf(1).divide(BigDecimal.valueOf(1000),2,BigDecimal.ROUND_UNNECESSARY);//抛出java.lang.ArithmeticException

比较大小:compareTo()

BigDecimal d = BigDecimal.valueOf(0.1);
BigDecimal e = BigDecimal.valueOf(0.1);
BigDecimal f = BigDecimal.valueOf(0.09999999);
BigDecimal g = BigDecimal.valueOf(0.10000001);
int n = d.compareTo(e);
System.out.println(n);//0 d等于e
n = d.compareTo(f);
System.out.println(n);//1 d大于f
n = d.compareTo(g);
System.out.println(n);//-1 d小于g

 

posted on 2022-07-19 16:26  胜者为王东恺  阅读(188)  评论(0编辑  收藏  举报

导航