一般出现丢失精度的场景:
- 整数值超出了整数类型的最大范围,就会丢失精度,所以java提供了java.math.BigInteger类来解决这个问题。
- 把一个数据范围大的类型的数值或者变量赋值给另一个数据范围较小的类型的变量,也可能会丢失精度。
- 直接使用浮点数进行小数计算,也不能准确计算,所以java提供了java.math.BigDecimal类来解决这个问题。
描述:商业计算往往要求结果精确,都是采用BigDecimal而不是浮点数Double或者Float来进行计算。
目录
使用BigDecimal需要注意除法divide的使用必须设置指定小数位和舍入模式。
为什么浮点数不能进行小数的精确运算?
float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。所以它们没有提供完全精确的结果,所以也就没办法用于要求精确结果的场合。具体底层为什么还未进行深入研究。
浮点数不能进行精确计算的举例:
/*--测试浮点数类型能否进行小数的精确计算--*/
@Test
public void testDouble() {
System.out.println(2.3 - 1.3);// 0.9999999999999998
System.out.println(1.4 - 1.3);// 0.09999999999999987
System.out.println(62556.0*0.12);//7506.719999999999
// 上面表明双精度浮点数不能进行精确的小数计算
System.out.println(2.3f - 1.3f);// 1.0
System.out.println(1.4f - 1.3f);// 0.100000024
// 上面表明单精度浮点数也不能进行精确的小数计算
}
BigDecimal的错误用法举例:
/*测试BigDecimal能否进行小数的精确计算*/
@Test
public void testBigDectimal1(){
BigDecimal loanAmount= new BigDecimal(62556.50);//用信贷款金额
BigDecimal loanRate=new BigDecimal(0.12);//执行年利率
//计算得到利息
BigDecimal interest = loanAmount.multiply(loanRate);
System.out.println(interest);//7506.779999999999722193333440145579515956342220306396484375
int compareTo = interest.compareTo(new BigDecimal(7506.78));
System.out.println(compareTo);//-1
}
BigDecimal正确用法举例:
/*测试BigDecimal能否进行小数的精确计算*/
@Test
public void testBigDectimal2(){
BigDecimal loanAmount= new BigDecimal("62556.50");//用信贷款金额
BigDecimal loanRate=new BigDecimal("0.12");//执行年利率
//计算得到利息
BigDecimal interest = loanAmount.multiply(loanRate);
System.out.pri