一、概述
BigDecimal主要用来对超过16位有效位的数进行精确的运算,继承了Number类,并且实现了Comparable接口。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理,所以就需要用到BigDecimal。具有以下特点:
- 对于需要精确计算的结果,则必须使用BigDecimal类来操作。对于不需要准确计算精度的数字,可以直接使用Float和Double处理,但Double.valueOf(String) 和Float.valueOf(String)会丢失精度。
- BigDecimal所创建的是对象,不能使用算术运算符(+、-、*、/等)直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。
- BigDecimal是不可变的,每次操作都会返回一个新的BigDecimal对象。
二、常用方法
1、构造方法
- 1)、BigDecimal(int val):将整型转换为BigDecimal。
- 2)、BigDecimal(long val):将长整型转换为BigDecimal。
- 3)、BigDecimal(double val):将双精度浮点型转换为BigDecimal。
- 4)、BigDecimal(String val):将字符串转换为BigDecimal。
// 构造方法
// 1、BigDecimal(int val):将整型转换为BigDecimal。
BigDecimal intDecimal = new BigDecimal(1);
System.out.println("将整型转换为BigDecimal:" + intDecimal); // 1
// 2、BigDecimal(long val):将长整型转换为BigDecimal。
BigDecimal longDecimal = new BigDecimal(1111L); // 1111
System.out.println("将长整型转换为BigDecimal:" + longDecimal);
// 3、BigDecimal(double val):将双精度浮点型转换为BigDecimal。
BigDecimal doubleBigDecimal = new BigDecimal(123.456D); // 123.4560000000000030695446184836328029632568359375
System.out.println("将双精度浮点型转换为BigDecimal:" + doubleBigDecimal);
// 4、BigDecimal(String val):将字符串转换为BigDecimal。
BigDecimal stringBigDecimal = new BigDecimal("123.456");
System.out.println("将字符串转换为BigDecimal:" + stringBigDecimal); // 123.456
注意:直接用double作为参数有一定的不可预知性,所创建的BigDecimal并不是等于传入的值,如new BigDecimal(123.456D)实际上等于123.4560000000000030695446184836328029632568359375,所以当需要使用double类型来创建BigDecimal对象时,建议先使用Double.toString(double)方法将double转换为String,然后再使用BigDecimal(String)构造方法。
2、静态方法
主要为valueOf()方法,用于通过double或long获取BigDecimal对象,有以下三种形式进行转换(重载):
- BigDecimal valueOf(double val) :返回一个表示指定的 double 值的 BigDecimal 对象。
- BigDecimal valueOf(long val):返回一个表示指定 long 值 的 BigDecimal 对象。
- static BigDecimal valueOf(long unscaledVal, int scale):通过long值获取BigDecimal对象,并指定缩放倍数(0为不缩放,正数为缩小10的n次方倍,负数为放大10的n次方倍)。
// 1、valueOf()
// 1)、valueOf(double d):通过double获取BigDecimal对象
BigDecimal b1 = BigDecimal.valueOf(123.456D);
System.out.println("通过double获取BigDecimal对象:" + b1); // 输出123.456
// 2)、valueOf(Long l):通过Long获取BigDecimal对象
BigDecimal b2 = BigDecimal.valueOf(123L);
System.out.println("通过Long获取BigDecimal对象:" + b2); // 输出123
// 3)、valueOf(String s, int scale):通过Long获取BigDecimal对象,并指定缩放倍数。
BigDecimal b3 = BigDecimal.valueOf(123L, 0);
System.out.println("将123L转成BigDecimal对象(缩小0倍):" + b3); // 输出123
BigDecimal b4 = BigDecimal.valueOf(123L, 1);
System.out.println("将123L转成BigDecimal对象(缩小10的1次方倍):" + b4); // 输出12.3
BigDecimal b5 = BigDecimal.valueOf(123L, 2);
System.out.println("将123L转成BigDecimal对象(缩小10的2次方倍):" + b5); // 输出1.23
BigDecimal b6 = BigDecimal.valueOf(123L, -1);
System.out.println("将123L转成BigDecimal对象(缩小10的-1次方倍):" + b6); // 输出1.23E+3
3、成员方法
3.1 xxxValue()系列的方法:将BigDecimal 转换为数值型基本数据类型,主要方法如下所示:
- byte byteValue():以byte形式返回该BigDecimal 值。
- short shortValue():以short 形式返回该BigDecimal 值。
- int intValue():以int 形式返回该BigDecimal 值。
- long longValue():以long 形式返回该BigDecimal 值。
- float floatValue():以float 形式返回该BigDecimal 值。
- double doubleValue():以double形式返回该BigDecimal 值。
// 1、转换为基本数据类型
BigDecimal num = new BigDecimal("123.456");
byte byteValue = num.byteValue();
System.out.println("以byte形式返回:" + byteValue); // 输出123
short shortValue = num.shortValue();
System.out.println("以short形式返回:" + shortValue); // 输出123
int intValue = num.intValue();
System.out.println("以int形式返回:" + intValue); // 输出123
long longValue = num.longValue();
System.out.println("以long形式返回:" + longValue); // 输出123
float floatValue = num.floatValue();
System.out.println("以float形式返回:" + floatValue); // 输出123.456
double doubleValue = num.doubleValue();
System.out.println("以double形式返回:" + doubleValue); // 输出123.456
3.2 String toString():将double转换为字符串。
// 2、String toString():将BigDecimal转换为字符串
BigDecimal num = new BigDecimal("123.456");
String numStr1 = num.toString();
System.out.println(numStr1); // 输出123.456
3.3 int compareTo(BigDecimal val):将当前BigDecimal与指定BigDecimal进行数值比较,返回一个整型数值。
- 如果返回值 < 0,表示当前对象小于指定对象。
- 如果返回值 = 0,表示当前对象等于指定对象。
- 如果返回值 > 0,表示当前对象大于指定对象。
// 3、int compareTo(BigDecimal val):比较方法compareTo
BigDecimal num1 = new BigDecimal("33.3");
BigDecimal num2 = new BigDecimal("13.3");
BigDecimal num3 = new BigDecimal("33.3");
System.out.println(num1.compareTo(num2)); // 输出1
System.out.println(num2.compareTo(num1)); // 输出-1
System.out.println(num1.compareTo(num3)); // 输出0
3.4 算术方法:主要为加减乘除运算,返回一个结果BigDecimal,主要方法如下所示:
- BigDecimal add(BigDecimal augend):将当前BigDecimal对象与指定BigDecimal对象相加。
- BigDecimal subtract(BigDecimal subtrahend):将当前BigDecimal对象与指定BigDecimal对象相减。
- BigDecimal multiply(BigDecimal multiplicand):将当前BigDecimal对象与指定BigDecimal对象相乘。
- BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode):将当前BigDecimal对象与指定BigDecimal对象相除,并设置小数点后保留的位数,以及舍入模式。常见的舍入模式主要有以下几种:
- RoundingMode.UP:向远离零的方向舍入。
- RoundingMode.DOWN:向接近零的方向舍入。
- RoundingMode.CEILING:向正无限方向舍入。
- RoundingMode.FLOOR:向负无限方向舍入。
- RoundingMode.HALF_UP:四舍五入。
- RoundingMode.HALF_DOWN:五舍六入。
- RoundingMode.HALF_EVEN:银行家舍入法,主要用于美国,可以减小舍入误差的累积。
// 算术方法
BigDecimal num1 = new BigDecimal("33.3");
BigDecimal num2 = new BigDecimal("13");
// 1、add(BigDecimal augend):相加
System.out.println("相加:" + num1.add(num2)); // 输出46.3
// 2、subtract(BigDecimal subtrahend):相减
System.out.println("相减:" + num1.subtract(num2)); // 输出20.3
// 3、multiply(BigDecimal multiplicand):相乘
System.out.println("相乘:" + num1.multiply(num2)); // 输出432.9
// 4、divide(BigDecimal divisor, RoundingMode roundingMode):相除并设置舍入模式
System.out.println("相除(设置仅保留两位小数,舍入模式为四舍五入):" + num1.divide(num2, 2, RoundingMode.HALF_UP)); // 输出2.56
System.out.println("相除(设置仅保留一位小数,舍入模式为舍去):" + num1.divide(num2, 1, RoundingMode.FLOOR)); // 输出2.5
3.5 BigDecimal setScale(int newScale, RoundingMode roundingMode):设置小数的位数,并指定舍入模式,返回一个结果BigDecimal。
// 5、setScale(保留位数,舍入方式):设置小数位数
BigDecimal value = new BigDecimal("123.456789");
BigDecimal scaledValue1 = value.setScale(2, RoundingMode.HALF_UP);
System.out.println("设置保留两位小数,舍入模式为四舍五入:" + scaledValue1); // 输出 123.46
BigDecimal scaledValue2 = value.setScale(3, RoundingMode.FLOOR);
System.out.println("设置保留三位小数,舍入模式为舍去:" + scaledValue2); // 输出 123.456
3.6 BigDecimal abs():获取当前BigDecimal的绝对值,返回一个结果BigDecimal。
// 6、abs():取绝对值
BigDecimal bigDecimal = new BigDecimal("-5.5");
BigDecimal positive = bigDecimal.abs(); // 取绝对值,结果为 5.5
System.out.println("取绝对值:" + positive);
3.7 取最大值和最小值:
- BigDecimal max(BigDecimal val):取当前BigDecimal与指定BigDecimal的最大值。
- BigDecimal min(BigDecimal val):取当前BigDecimal与指定BigDecimal的最小值。
// 7、取最值
BigDecimal num1 = new BigDecimal("33.3");
BigDecimal num2 = new BigDecimal("13");
// 1)、max(BigDecimal val):取最大值
System.out.println("最大值:" + num1.max(num2)); // 输出33.3
// 2)、min(BigDecimal val):取最小值
System.out.println("最小值:" + num1.min(num2)); // 输出13
3.8 BigDecimal[] divideAndRemainder(BigDecimal divisor):将当前BigDecimal对象与指定BigDecimal对象相除,返回一个长度为2的BigDecimal数组,第一个元素为商,第二个元素为余数。
// 8、divideAndRemainder(BigDecimal divisor):除法并返回商和余数
BigDecimal bigDecimal1 = new BigDecimal("123.45");
BigDecimal bigDecimal2 = new BigDecimal("10");
// 返回一个长度为2的BigDecimal数组,第一个元素为商,第二个元素余数
BigDecimal[] result = bigDecimal1.divideAndRemainder(bigDecimal2);
System.out.println(Arrays.toString(result)); // 输出[12.00, 3.45]
System.out.println("商: " + result[0]); // 输出12.00
System.out.println("余数: " + result[1]); // 输出3.45
3.9 BigDecimal divideToIntegralValue(BigDecimal divisor):计算除法的商,并返回其整数部分,余数将被舍弃。
// 9、divideToIntegralValue(BigDecimal divisor):计算除法的商,并返回其整数部分,余数将被舍弃。
BigDecimal bigDecimal1 = new BigDecimal("123.45");
BigDecimal bigDecimal2 = new BigDecimal("10");
BigDecimal result = bigDecimal1.divideToIntegralValue(bigDecimal2);
System.out.println("商的整数部分: " + result); // 输出 12.00
三、类型转换
1、BigDecimal与基本数据类型的转换
主要为int、long、float、double这几个基本数据类型与BigDecimal的相互转换,它们的包装类同样适用该方法(自动拆箱)。
1.1 BigDecimal → 基本数据类型:BigDecimal对象.xxxValue(); 成员方法
// BigDecimal对象.xxxValue():BigDecimal转换为基本数据类型
BigDecimal num = new BigDecimal("123.456");
// 1、BigDecimal转int
int intValue = num.intValue();
System.out.println(intValue); // 输出123
// 2、BigDecimal转long
long longValue = num.longValue();
System.out.println(longValue); // 输出123
// 3、BigDecimal转float
float floatValue = num.floatValue();
System.out.println(floatValue); // 输出123.456
// 4、BigDecimal转double
double doubleValue = num.doubleValue();
System.out.println(doubleValue); // 输出123.456
1.2 基本数据类型 → BigDecimal:BigDecimal.valueOf(基本数据类型值); 静态方法
// BigDecimal valueOf(val):基本数据类型转换为 BigDecimal
// 1、int转BigDecimal
int intToBigDecimal = 123;
BigDecimal bigDecimalFromInt = BigDecimal.valueOf(intToBigDecimal);
System.out.println(bigDecimalFromInt); // 输出123
// 2、long转BigDecimal
long longToBigDecimal = 1234567890123L;
BigDecimal bigDecimalFromLong = BigDecimal.valueOf(longToBigDecimal);
System.out.println(bigDecimalFromLong); // 输出1234567890123
// 3、float转BigDecimal
float floatToBigDecimal = 123.456f;
BigDecimal bigDecimalFromFloat = BigDecimal.valueOf(floatToBigDecimal);
System.out.println(bigDecimalFromFloat); // 输出123.45600128173828
// 4、double转BigDecimal
double doubleToBigDecimal = 123.456;
BigDecimal bigDecimalFromDouble = BigDecimal.valueOf(doubleToBigDecimal);
System.out.println(bigDecimalFromDouble); // 输出123.456
2、BigDecimal与字符串类型的转换
2.1 BigDecimal → 字符串:通过BigDecimal的构造方法BigDecimal(String val)进行转换。
// String toString():BigDecimal转字符串
BigDecimal bigDecimal = BigDecimal.valueOf(123L);
String stringValue = bigDecimal.toString();
System.out.println(stringValue); // 输出123
2.2 字符串 → BigDecimal:使用BigDecimal的成员方法String toString()进行转换。
// String toString():字符串转BigDecimal
String strValue = "123.456";
BigDecimal convertedBigDecimal = new BigDecimal(strValue);
System.out.println(convertedBigDecimal); // 输出123.456
四、格式化输出
BigDecimal类本身并没有提供格式化方法,但可以使用DecimalFormat类来格式化BigDecimal对象的输出。DecimalFormat 是 Java 中用于格式化数字的一个类,它属于 java.text 包,允许你指定一个模式(pattern)来控制数字的显示格式,包括小数点后的位数、千位分隔符、货币符号等。
1、基本使用
1.1 创建DecimalFormat对象,并指定格式:DecimalFormat df = new DecimalFormat("格式字符串");
1.2 调用DecimalFormat对象的format()方法对BigDecimal进行格式化: String format1 = df.format(bd1);
// 基本使用
BigDecimal bd1 = new BigDecimal("123.456789");
BigDecimal bd2 = new BigDecimal("123");
// 1、创建DecimalFormat对象,并指定格式
// 设置格式为0.00,即保留两位小数,多余小数四舍五入,小数不足两位时补零
DecimalFormat df = new DecimalFormat("0.00");
// 2、调用DecimalFormat对象的format()方法对BigDecimal进行格式化
String formatted1 = df.format(bd1);
String formatted2 = df.format(bd2);
System.out.println(formatted1); // 输出123.46
System.out.println(formatted2); // 输出123.00
2、DecimalFormat格式字符串:由一系列的模式字符组成,每个字符都有其特定的含义:
- 0 → 表示数字,如果位数不够会自动补零。
- # → 表示数字,但如果位数不够时不显示。
- . → 表示小数分隔符。
- , → 千分位分隔符。
- % → 表示数值乘以100并拼接百分号。
- ‰ → 表示数值乘以1000并拼接千分号。
- ¤ → 货币记号,输出时用货币符号代替。如果连续出现两个,则输出时用国际货币符号替换。
- E → 表示科学计数法。
- - → 表示负号。
- + → 表示正号。
;
→用于分隔正负数格式。'
→用于在格式中添加文本字符(例如货币符号)。
3、常见案例:
// 1、基本数字格式化
// 1)、整数部分无限制,保留两位小数
BigDecimal bigDecimal1 = new BigDecimal("1234567.890123");
BigDecimal bigDecimal2 = new BigDecimal("12.3456");
DecimalFormat df1 = new DecimalFormat("#,###.00");
System.out.println(df1.format(bigDecimal1)); // 输出1,234,567.89
System.out.println(df1.format(bigDecimal2)); // 输出12.35
// 2)、整数部分至少三位,不足补零,小数部分两位
DecimalFormat df2 = new DecimalFormat("#,000.00");
System.out.println(df2.format(bigDecimal1)); // 输出1,234,567.89
System.out.println(df2.format(bigDecimal2)); // 输出012.35
// 2、百分比格式化:百分比格式并保留两位小数
BigDecimal bigDecimal3 = new BigDecimal("0.1234");
DecimalFormat df3 = new DecimalFormat("0.00%");
System.out.println(df3.format(bigDecimal3)); // 输出12.34%
// 3、货币格式化:货币格式,使用默认货币符号(根据Locale设置):
BigDecimal bigDecimal4 = new BigDecimal("1234567.89");
DecimalFormat df4 = new DecimalFormat("¤#,###.00");
DecimalFormatSymbols symbols1 = new DecimalFormatSymbols(Locale.US);
df4.setDecimalFormatSymbols(symbols1);
System.out.println(df4.format(bigDecimal4)); // 输出$1,234,567.89
// 4、科学计数法格式化:科学计数法,保留两位小数
BigDecimal bigDecimal5 = new BigDecimal("1234567.1234");
DecimalFormat df5 = new DecimalFormat("0.00E0");
System.out.println(df5.format(bigDecimal5)); // 输出1.23E6
// 5、自定义千位分隔符和小数分隔符
BigDecimal bigDecimal6 = new BigDecimal("1234567.890");
DecimalFormat df6 = new DecimalFormat("#,###.00");
DecimalFormatSymbols symbols2 = new DecimalFormatSymbols();
symbols2.setGroupingSeparator(';'); // 自定义千位分隔符为分号
symbols2.setDecimalSeparator(','); // 自定义小数分隔符为逗号
df6.setDecimalFormatSymbols(symbols2);
System.out.println(df6.format(bigDecimal6)); // 输出1;234;567,89