BigDecimal使用注意事项⚠️

背景

       我毕业后的第一家公司是在一个金融互联网工作,在计算组合的净值和收益的时候就会用到一些小数的计算,用过Java的同学应该会知道小数在计算机存储的时候是个近似值,直接用Double或者Float计算两个小数因为计算的结果是近似值,所以在一些场景下会出现问题,但是你要是对BigDecimal 熟悉的话,在计算小数的时候直接上BigDecimal就能避免上述问题。
BigDecimal使用注意事项⚠️_第1张图片


BigDecimal 概述

         Java 在 java.math 包中提供的 API 类 BigDecimal,用来对超过 16 位有效位的数进行精确的运算。双精度浮点型变量 Double 可以处理 16 位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理,则必须使用 BigDecimal 类来操作。BigDecimal 对象提供了传统的 +、-、*、/ 等算术运算符对应的方法,通过这些方法进行相应的操作。BigDecimal 都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。

使用和注意事项

  1. 创建对象使用BigDecimal的valueOf()还是new BigDecimal()视场景而定
    BigDecimal使用注意事项⚠️_第2张图片
           如果传入的有效位数小于16,且要求计算结果准确,建议用BigDecimal的valueOf()。之所以会出现上述现象,是因为 new BigDecimal() 时,传入的 0.1 已经是浮点类型了,鉴于上面说的这个值只是近似值,在使用 new BigDecimal ()时就把这个近似值完整的保留下来了。而 BigDecimal.valueOf() 则不同,在 valueOf() 内部使用toString() 方法,将浮点类型的值转换成了字符串,因此不存在精度丢失问题了。但是BigDecimal的valueOf()接受的Double有效数字最多只能是16位,所以当传入的参数大于16位时使用new BigDecimal()。BigDecimal使用注意事项⚠️_第3张图片

2.如果比较两个 BigDecimal 的值是否相等建议使用compareTo()而不是 equals();
BigDecimal使用注意事项⚠️_第4张图片
       这是因为equals()方法不仅判断了数值是否相等还判断了精度是否相等,而 compareTo() 方法实现了 Comparable 接口,真正比较的是值的大小,返回的值为 - 1(小于),0(等于),1(大于)。

3.对BigDecimal 进行计算时记得要设置计算结果的精度和舍入模式,不然某些j计算结果可能仍然存在问题;
BigDecimal使用注意事项⚠️_第5张图片
对于0.1/0.3无法计算精确值,所以就会抛ArithmeticException 异常,这时就必须要指定保留的精度和舍入模式,通常我们使用的四舍五入即 RoundingMode.HALF_UP。
舍入模式共有如下 8 种:

  • RoundingMode.UP:舍入远离零的舍入模式。在丢弃非零部分之前始终增加数字 (始终对非零舍弃部分前面的数字加 1)。注意,此舍入模式始终不会减少计算值的大小。
  • RoundingMode.DOWN:接近零的舍入模式。在丢弃某部分之前始终不增加数字 (从不对舍弃部分前面的数字加 1,即截短)。注意,此舍入模式始终不会增加计算值的大小。
  • RoundingMode.CEILING:接近正无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUNDUP 相同;如果为负,则舍入行为与ROUNDDOWN 相同。注意,此舍入模式始终不会减少计算值。
  • RoundingMode.FLOOR:接近负无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUNDDOWN 相同;如果为负,则舍入行为与ROUNDUP 相同。注意,此舍入模式始终不会增加计算值。
  • RoundingMode.HALF_UP:向 “最接近的” 数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。注意,这是我们在小学时学过的舍入模式 (四舍五入)。
  • RoundingMode.HALF_DOWN:向 “最接近的” 数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同 (五舍六入)。
  • RoundingMode.HALF_EVEN:向 “最接近的” 数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUNDHALFUP 相同;如果为偶数,则舍入行为与 ROUNDHALF_DOWN 相同。注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。此舍入模式也称为 “银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。如果前一位为奇数,则入位,否则舍去。以下例子为保留小数点 1 位,那么这种舍入方式下的结果。1.15 ==> 1.2 ,1.25 ==> 1.2
  • RoundingMode.UNNECESSARY:断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出 ArithmeticException。

BigDecimal使用注意事项⚠️_第6张图片

你可能感兴趣的:(笔记,java)