BigDecimal
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。
在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。
BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
第一:注意使用BigDecimal时要使用new BigDecimal("10.245755")或BigDecimal.valueOf(10.245755)形式,不能使用new BigDecimal(10.245755),否则会导致精度出现问题
BigDecimal b1 = new BigDecimal(10.245755);
BigDecimal b2 = BigDecimal.valueOf(10.245755);
BigDecimal b3 = new BigDecimal("10.245755");
System.out.println("b1: " + b1);
System.out.println("b2: " + b2);
System.out.println("b3: " + b3);
运行结果为:
b1: 10.2457550000000008338929546880535781383514404296875
b2: 10.245755
b3: 10.245755
备注:一定要注意切记不能使用new BigDecimal(10.245755)这种形式!!!
第二:BigDecimal常用加减乘除运算
BigDecimal b1 = BigDecimal.valueOf(10.245755);
BigDecimal b2 = new BigDecimal("10.24575");
//加减法的精度跟参与运算的两个值里面精度长的那一个精度保持一致
System.out.println("b1 + b2: " + b1.add(b2));
System.out.println("b1 - b2: " + b1.subtract(b2));
//乘法精度等于两个数精度的和
System.out.println("b1 x b2: " + b1.multiply(b2));
//除法,如果结果是无限循环小数,会报异常java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
//对结果做处理,保留特定位数小数
System.out.println("b1 / b2: " + b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP));
//注意,这是错误处理,这样仍然会存在无限循环
System.out.println("b1 / b2: " + b1.divide(b2).setScale(2, BigDecimal.ROUND_HALF_UP));
//此时需要对结果做处理,保留特定位数小数
System.out.println("b1 / b2: " + b1.divide(b2));
运行结果:
b1 + b2: 20.491505
b1 - b2: 0.000005
b1 x b2: 104.97544429125
b1 / b2: 1.00
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
第三、BigDecimal比较大小
BigDecimal b1 = BigDecimal.valueOf(10.245755);
BigDecimal b2 = new BigDecimal("10.245755");
BigDecimal b3 = new BigDecimal("11.245755");
BigDecimal b4 = new BigDecimal("9.245755");
//BigDecimal类型的比较需要用compareTo方法,==返回0,ab返回1
System.out.println("b1 == b2: " + b1.compareTo(b2));
System.out.println("b1 < b3: " + b1.compareTo(b3));
System.out.println("b1 > b4: " + b1.compareTo(b4));
运行结果:
b1 == b2: 0
b1 < b3: -1
b1 > b4: 1
第四:BigDecimal取绝对值,去尾保留,四舍五入保留等运算
BigDecimal b1 = BigDecimal.valueOf(-10.245755);
BigDecimal b2 = new BigDecimal("10.245755");
BigDecimal b3 = new BigDecimal("10.545755");
//b1和b2的绝对值
System.out.println("b1绝对值: " + b1.abs());
System.out.println("b2绝对值: " + b2.abs());
//通过setScale()方法将小数点后的位数截断
//setScale()并将小数点后的位数设置为0,以截断小数点后的位数。ROUND_DOWN是舍位模式之一,它表示直接截断小数点后的位数,不进行四舍五入
System.out.println("b2小数点截断: " + b2.setScale(0, BigDecimal.ROUND_DOWN));
System.out.println("b3小数点截断: " + b3.setScale(0, BigDecimal.ROUND_DOWN));
System.out.println("b2小数点截断: " + b2.setScale(2, BigDecimal.ROUND_DOWN));
System.out.println("b3小数点截断: " + b3.setScale(2, BigDecimal.ROUND_DOWN));
//setScale()并将小数点后的位数设置为0,以截断小数点后的位数。ROUND_UP是舍位模式之一,它表示直接截断小数点后的位数,直接进1
System.out.println("b2小数点截断: " + b2.setScale(0, BigDecimal.ROUND_UP));
System.out.println("b3小数点截断: " + b3.setScale(0, BigDecimal.ROUND_UP));
System.out.println("b2小数点截断: " + b2.setScale(2, BigDecimal.ROUND_UP));
System.out.println("b3小数点截断: " + b3.setScale(2, BigDecimal.ROUND_UP));
//setScale()并将小数点后的位数设置为0,以截断小数点后的位数。ROUND_HALF_UP是舍位模式之一,它表示直接截断小数点后的位数,进行四舍五入
System.out.println("b2小数点截断: " + b2.setScale(0, BigDecimal.ROUND_HALF_UP));
System.out.println("b3小数点截断: " + b3.setScale(0, BigDecimal.ROUND_HALF_UP));
System.out.println("b2小数点截断: " + b2.setScale(2, BigDecimal.ROUND_HALF_UP));
System.out.println("b3小数点截断: " + b3.setScale(2, BigDecimal.ROUND_HALF_UP));
运行结果:
b1绝对值: 10.245755
b2绝对值: 10.245755
b2小数点截断: 10
b3小数点截断: 10
b2小数点截断: 10.24
b3小数点截断: 10.54
b2小数点截断: 11
b3小数点截断: 11
b2小数点截断: 10.25
b3小数点截断: 10.55
b2小数点截断: 10
b3小数点截断: 11
b2小数点截断: 10.25
b3小数点截断: 10.55
第五、BigDecimal类型转换
BigDecimal b1 = BigDecimal.valueOf(10.245755);
BigDecimal b2 = BigDecimal.valueOf(10.2457556545158512211222);
//BigDecimal类型转换
System.out.println("b1转int: " + b1.intValue());
System.out.println("b1转double: " + b1.doubleValue());
System.out.println("b1转long: " + b1.longValue());
System.out.println("b1转String: " + b1.toString());
System.out.println("b1转String: " + b1.toPlainString());
System.out.println("b1转String: " + b1.toEngineeringString());
System.out.println("====================================");
System.out.println("b2转int: " + b2.intValue());
System.out.println("b2转double: " + b2.doubleValue());
System.out.println("b2转long: " + b2.longValue());
System.out.println("b2转String: " + b2.toString());
System.out.println("b1转String: " + b2.toPlainString());
System.out.println("b1转String: " + b2.toEngineeringString());
运行结果:
b1转int: 10
b1转double: 10.245755
b1转long: 10
b1转String: 10.245755
b1转String: 10.245755
b1转String: 10.245755
====================================
b2转int: 10
b2转double: 10.24575565451585
b2转long: 10
b2转String: 10.24575565451585
b1转String: 10.24575565451585
b1转String: 10.24575565451585
补充案列如下:
注意,一般商业项目当中,BigDecimal用来做金额计算时,需要使用toPlainString()方法将BigDecimal转为String,这种方式不使用科学计数法,显示才是正常的数值
//案例一
BigDecimal b1 = new BigDecimal("0.000000123").setScale(9);
System.out.println(b1.toString());
System.out.println(b1.scale());
System.out.println(b1.unscaledValue());
//输出结果为
1.23E-7
0.000000123
9
123
//案例二
BigDecimal b2 = new BigDecimal("0.000001234").setScale(9);
System.out.println(b2.toString());
System.out.println(b2.toPlainString());
System.out.println(b2.scale());
System.out.println(b2.unscaledValue());
//输出结果为
0.000001234
0.000001234
9
1234
//案例三
BigDecimal b3 = new BigDecimal("0.123000000").setScale(9);
System.out.println(b3.toString());
System.out.println(b3.toPlainString());
System.out.println(b3.scale());
System.out.println(b3.unscaledValue());
//输出结果为
0.123000000
0.123000000
9
123000000
//案例四
BigDecimal b4 = new BigDecimal("123000000");
System.out.println(b4.toString());
System.out.println(b4.toPlainString());
System.out.println(b4.scale());
System.out.println(b4.unscaledValue());
//输出结果为
123000000
123000000
0
123000000
//案例五
//Double d = 12345678d; Double d = 12345678.0; 效果一样
Double d = (double) 12345678;
BigDecimal b5 = BigDecimal.valueOf(d);
System.out.println(d);
System.out.println(b5.toString());
System.out.println(b5.toPlainString());
System.out.println(b5.scale());
System.out.println(b5.unscaledValue());
//输出结果为
1.2345678E7
12345678
12345678
0
12345678