引文

系统中,在涉及到金额的运算中,往往都会涉及到小数点,而浮点数在计算机中会存在精度丢失的问题,但是像涉及到金额的业务对计算结果的精度要求较高,你们是怎么处理的?
通常来说有两种解决方式:

  • 以分为单位,用Long来存储变量
  • 以BigInteger或BigDecimal来处理

BigInteger和BigDecimal

按照我的认知来说:
在Java中,数值无非就是两种整数和浮点数,常用的基本数据类型就是int,float,但是这两个基本数据类型的范围太小了,于是还有long、double。
后来为了迎合Java面向对象的思想,又有了包装类Integer、Float、Long、Double,但是这些包装类就是对基本数据类型的封装,表示数据的范围和精度并不会变化。
因此又来了新的两个类BigInteger和BigDecimal:

  • BigInteger可以用来表示任意长度的整数
  • BigDecimal可以用来表示任意长度的浮点数
    BigInteger和BigDecimal的出现,这两个的底层原理就是使用数组来保存每一位数值,使得我们再也不用担心数据过长的问题。(hhh还记得高精算法吗?就是这个)
    这两个类的用法基本一致
    下面来说一下这两个的用法

创建:

  1. 直接new BigXxx()
  2. BigXxx.valueOf()

基本使用:

  • 加add()
  • 减substract()
  • 乘multiply()
  • 除divide()
  • 比较compareTo()、max()、min()
  • 求余remainder()
  • 商和余数一起返回divideAndRemainder()
    还有转换为基本数据类型:intValue()、doubleValue()…,可能会丢失精度的问题,因为BigInteger和BigDecimal能表示的范围远远大于long和double

建议

  1. 尽量使用字符串来创建BigXxx实例。
    在创建BigXxx实例时,尽量使用形参是String的方法,因为用String表示数值能表示的更大,而且用字符串表示数值不会存在精度丢失的问题。
    而使用int或double的参数,能表示的数值范围受限,同时会存在精度丢失的问题,因为浮点数在计算机中不能精确表示。

  2. 在比较时,不要使用equals()方法,要使用compareTo()、max()、min()

  3. 在两个BigXxx在进行除运算时,一定要指定小数点保留位数。
    两者相除的结果是无限循环小数,那么一定要指定保留的小数点位数,否则报错。
    例如2÷3 = 0.66666无限循环小数

10-05 21:17