Java程序员编程里经常会涉及货币金钱,这个时候BigDecimal就派上用场了,下面我就来详解BigDecimal@mikechen
什么是BigDecimal?
BigDecimal 是Java在java.math包中提供的API类,主要是用于金钱等要求高精度数值的计算。
Java 类中的 BigDecimal 提供算术运算(加、减、乘、除)、舍入、比较、散列和格式转换,BigDecimal 表示不可变的任意精度的有符号十进制数。
为什么需要BigDecimal?
前面学习Java8大基本类型的时候,我们可以使用float 和 double来表示浮点型数字,但是这里有一个问题那就是基本数据类型float 和 double不应该用于高精度数据的表示。
例如货币,因为浮点类型的float 和 double会丢失数据的精度。
举一个例子:
double d1 = 374.56; double d2 = 374.26; System.out.println( "d1 - d2 = " + ( d1 - d2 ));
这里本应输出的是0.30,但是实际上输出如下:
d1 - d2 = 0.30000000000001137
float和double类型尤其不适合用于货币运算,因为要让一个float或double精确的表示0.1或者10的任何其他负数次方值是不可能的。
其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10,浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。
这就是为什么在金融相关的程序里数据类型如此重要的原因,所以我们更好的选择是BigDecimal 而不是float 和 double。
BigDecimal常用构造函数
1.创建一个具有参数所指定整数值的对象
BigDecimal(int)
2.创建一个具有参数所指定双精度值的对象
BigDecimal(double)
3.创建一个具有参数所指定长整数值的对象
BigDecimal(long)
4.创建一个具有参数所指定以字符串表示的数值的对象
BigDecimal(String)
推荐使用第四种:BigDecimal(String)
BigDecimal的常用方法
1.获取值
// 获取值 bigDecimal.byteValue(); bigDecimal.doubleValue(); bigDecimal.longValue(); bigDecimal.intValue(); bigDecimal.shortValue();
2.运算
// 运算 // 每次操作都需要重新赋值才有效果,后面有代码演示 bigDecimal = bigDecimal.add(BigDecimal b); // 加 bigDecimal = bigDecimal.subtract(BigDecimal b); // 减 bigDecimal = bigDecimal.multiply(BigDecimal b); // 乘 bigDecimal = bigDecimal.divide(BigDecimal b); // 除
3.比较大小
// 比较大小 bigDecimal.compareTo(BigDecimal b);
4.设置精度
// 设置精度 bigDecimal = bigDecimal.setScale(int);
5.绝对值
// 绝对值 bigDecimal.abs();
BigDecimal的使用示例
1.加减乘除
package com.mikechen.util; import java.math.BigDecimal; public class ArithUtil { // 除法运算默认精度 private static final int DEF_DIV_SCALE = 10; /** * 精确加法 */ public static double add(double value1, double value2) { BigDecimal b1 = BigDecimal.valueOf(value1); BigDecimal b2 = BigDecimal.valueOf(value2); return b1.add(b2).doubleValue(); } /** * 精确减法 */ public static double sub(double value1, double value2) { BigDecimal b1 = BigDecimal.valueOf(value1); BigDecimal b2 = BigDecimal.valueOf(value2); return b1.subtract(b2).doubleValue(); } /** * 精确乘法 */ public static double mul(double value1, double value2) { BigDecimal b1 = BigDecimal.valueOf(value1); BigDecimal b2 = BigDecimal.valueOf(value2); return b1.multiply(b2).doubleValue(); } /** * 精确除法 使用默认精度 */ public static double div(double value1, double value2) throws IllegalAccessException { return div(value1, value2, DEF_DIV_SCALE); } /** * 精确除法 * @param scale 精度 */ public static double div(double value1, double value2, int scale) throws IllegalAccessException { if(scale < 0) { throw new IllegalAccessException("精确度不能小于0"); } BigDecimal b1 = BigDecimal.valueOf(value1); BigDecimal b2 = BigDecimal.valueOf(value2); // return b1.divide(b2, scale).doubleValue(); return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); } public static void main(String[] args) throws IllegalAccessException { double value1=1.2345678912311; double value2=9.1234567890123; BigDecimal value3=new BigDecimal(Double.toString(value1)); BigDecimal value4=new BigDecimal(Double.toString(value2)); System.out.println("精确加法================="+ArithUtil.add(value1, value2)); System.out.println("精确减法================="+ArithUtil.sub(value1, value2)); System.out.println("精确乘法================="+ArithUtil.mul(value1, value2)); System.out.println("精确除法 使用默认精度 ================="+ArithUtil.div(value1, value2)); System.out.println("精确除法 设置精度================="+ArithUtil.div(value1, value2,20)); }
2.比较大小
package com.mikechen.util; import java.math.BigDecimal; public class ArithUtil { // 除法运算默认精度 private static final int DEF_DIV_SCALE = 10; /** * 比较大小 */ public static boolean equalTo(BigDecimal b1, BigDecimal b2) { if(b1 == null || b2 == null) { return false; } return 0 == b1.compareTo(b2); } public static void main(String[] args) throws IllegalAccessException { double value1=1.2345678912311; double value2=9.1234567890123; BigDecimal value3=new BigDecimal(Double.toString(value1)); BigDecimal value4=new BigDecimal(Double.toString(value2)); System.out.println("比较大小 ================="+ArithUtil.equalTo(value3, value4)); }
3.四舍五入
package com.mikechen.util; import java.math.BigDecimal; public class ArithUtil { // 除法运算默认精度 private static final int DEF_DIV_SCALE = 10; /** * 四舍五入 * @param scale 小数点后保留几位 */ public static double round(double v, int scale) throws IllegalAccessException { return div(v, 1, scale); } public static void main(String[] args) throws IllegalAccessException { double value1=1.2345678912311; System.out.println("四舍五入 小数点后保留几位 ================="+ArithUtil.round(value1, 10)); }
BigDecimal的总结
以上我就主要介绍了BigDecimal的构造,以及BigDecimal的常用方法,希望对你掌握BigDecimal有所帮助。
mikechen睿哥
mikechen睿哥,十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》