引文
系统中,在涉及到金额的运算中,往往都会涉及到小数点,而浮点数在计算机中会存在精度丢失的问题,但是像涉及到金额的业务对计算结果的精度要求较高,你们是怎么处理的?
通常来说有两种解决方式:
- 以分为单位,用Long来存储变量
- 以BigInteger或BigDecimal来处理
BigInteger和BigDecimal
按照我的认知来说:
在Java中,数值无非就是两种整数和浮点数,常用的基本数据类型就是int,float,但是这两个基本数据类型的范围太小了,于是还有long、double。
后来为了迎合Java面向对象的思想,又有了包装类Integer、Float、Long、Double,但是这些包装类就是对基本数据类型的封装,表示数据的范围和精度并不会变化。
因此又来了新的两个类BigInteger和BigDecimal:
- BigInteger可以用来表示任意长度的整数
- BigDecimal可以用来表示任意长度的浮点数
BigInteger和BigDecimal的出现,这两个的底层原理就是使用数组来保存每一位数值,使得我们再也不用担心数据过长的问题。(hhh还记得高精算法吗?就是这个)
这两个类的用法基本一致
下面来说一下这两个的用法
创建:
- 直接new BigXxx()
- BigXxx.valueOf()
基本使用:
- 加add()
- 减substract()
- 乘multiply()
- 除divide()
- 比较compareTo()、max()、min()
- 求余remainder()
- 商和余数一起返回divideAndRemainder()
还有转换为基本数据类型:intValue()、doubleValue()…,可能会丢失精度的问题,因为BigInteger和BigDecimal能表示的范围远远大于long和double
建议
-
尽量使用字符串来创建BigXxx实例。
在创建BigXxx实例时,尽量使用形参是String的方法,因为用String表示数值能表示的更大,而且用字符串表示数值不会存在精度丢失的问题。
而使用int或double的参数,能表示的数值范围受限,同时会存在精度丢失的问题,因为浮点数在计算机中不能精确表示。 -
在比较时,不要使用equals()方法,要使用compareTo()、max()、min()
-
在两个BigXxx在进行除运算时,一定要指定小数点保留位数。
两者相除的结果是无限循环小数,那么一定要指定保留的小数点位数,否则报错。
例如2÷3 = 0.66666无限循环小数