一、DecimalFormat:数字格式化类
DecimalFormat是java.text包下的类,专门用于将数字(整数、浮点数)格式化为指定格式的字符串,支持千分位分隔、固定小数位、补 0 等需求。其核心是通过格式模式字符串定义输出格式。
1. 格式模式符号说明
先明确几个常用的格式符号含义:
- #:表示任意数字,不存在则不显示(例如格式#.##,数字 1.2 会显示为1.2,而非1.20);
- ,:千分位分隔符(每三位数字分隔,如 1234567 会显示为1,234,567);
- .:小数点分隔符,用于区分整数部分和小数部分;
- 0:表示数字,不存在则补 0(例如格式0.00,数字 1.2 会显示为1.20)。
2. 示例:格式化大额数字与固定小数位
java
import java.text.DecimalFormat;
public class Test {
public static void main(String[] args) {
// 定义格式:千分位分隔,保留4位小数
DecimalFormat decimalFormat = new DecimalFormat("###,###.0000");
// 格式化数字12553456.598795
System.out.println(decimalFormat.format(12553456.598795));
}
输出结果: 12,553,456.5988
解析: 格式###,###.0000中,###,###表示整数部分每三位用逗号分隔(千分位); .0000表示小数部分固定保留 4 位,不足则补 0,超出则四舍五入(原数字小数位是598795,四舍五入后为5988)。
3. 更多格式化场景示例
除了示例中的格式,DecimalFormat还支持多种实用格式,举例如下:
java
public class DecimalFormatDemo {
public static void main(String[] args) {
// 1. 整数部分补0(如固定3位整数,不足补0)
DecimalFormat df1 = new DecimalFormat("000");
System.out.println(df1.format(5)); // 输出:005
// 2. 保留2位小数,整数部分千分位
DecimalFormat df2 = new DecimalFormat("###,###.00");
System.out.println(df2.format(123456.7)); // 输出:123,456.70
// 3. 百分比格式(数字×100后加%)
DecimalFormat df3 = new DecimalFormat("0.00%");
System.out.println(df3.format(0.356)); // 输出:35.60%
// 4. 科学计数法(保留2位小数)
DecimalFormat df4 = new DecimalFormat("0.00E0");
System.out.println(df4.format(123456)); // 输出:1.23E5(即1.23×10^5)
}
4. 四舍五入说明
| 舍入模式 | 0.125 的结果 |
|---|---|
| HALF_UP (标准四舍五入) | 0.13 |
| HALF_EVEN (银行家舍入法) 默认 | 0.12 |
| UP (向上舍入) | 0.13 |
| DOWN (向下舍入) | 0.12 |
java
DecimalFormat formatter = new DecimalFormat("#.##");
formatter.setRoundingMode(RoundingMode.HALF_UP); // 设置为标准四舍五入
**核心总结:**DecimalFormat的关键是通过格式模式字符串定义规则,其中#和0用于控制数字位数(0强制补 0,#不强制),,用于千分位,.用于分隔整数和小数部分。
二、BigDecimal:高精度数值计算类
float和double是 Java 中的基本浮点类型,但由于二进制存储的特性,它们无法精确表示所有十进制小数(例如0.1用 double 存储时实际是近似值),在金融、电商等对精度要求极高的场景中会导致误差(如金额计算错误)。
BigDecimal是java.math包下的类,支持任意精度的数值计算,完美解决浮点精度问题。
1. 为什么需要 BigDecimal?
先看一个反例:用double计算 0.1+0.2 的结果:
java
System.out.println(0.1 + 0.2); // 输出:0.30000000000000004(存在精度误差)
这是因为0.1和0.2在二进制中无法精确表示,累加后误差被放大。而BigDecimal可以避免这种问题:
java
import java.math.BigDecimal;
public class BigDecimalDemo {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 输出:0.3(精确计算)
}
2. 基本用法:创建与运算
BigDecimal的创建和加法运算:
java
// 创建BigDecimal对象(注意:不推荐用double构造,原因见下文)
BigDecimal bigDecimal = new BigDecimal(1.555555555555555);
BigDecimal bigDecimal1 = new BigDecimal(2.999999999999);
// 加法运算
System.out.println(bigDecimal.add(bigDecimal1));
// 输出结果(可能存在误差):
4.555555555554555
这里有个坑:用double作为参数构造BigDecimal时,由于double本身的精度问题,BigDecimal会保留其近似值,导致计算结果仍有误差。推荐用String作为构造参数,确保精度:
java
// 正确写法:用String构造
BigDecimal a = new BigDecimal("1.555555555555555");
BigDecimal b = new BigDecimal("2.999999999999");
System.out.println(a.add(b)); // 输出:4.555555555554555(精确)
3. 常用运算方法
BigDecimal提供了丰富的运算方法,支持加减乘除等操作,注意运算后需用变量接收结果(BigDecimal是不可变类,运算不会修改原对象):
java
public class BigDecimalOperation {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3");
// 加法
BigDecimal sum = a.add(b);
System.out.println("和:" + sum); // 输出:13.5
// 减法
BigDecimal sub = a.subtract(b);
System.out.println("差:" + sub); // 输出:7.5
// 乘法
BigDecimal mul = a.multiply(b);
System.out.println("积:" + mul); // 输出:31.5
// 除法(需指定保留小数位和舍入模式,避免除不尽报错)
BigDecimal div = a.divide(b, 2, BigDecimal.ROUND_HALF_UP);
// 解释:divide(除数, 保留小数位数, 舍入模式)
// ROUND_HALF_UP:四舍五入
System.out.println("商:" + div); // 输出:3.50
}
}
DecimalFormat是java.text包下的类,专门用于将数字(整数、浮点数)格式化为指定格式的字符串,支持千分位分隔、固定小数位、补 0 等需求。其核心是通过格式模式字符串定义输出格式。
- 格式模式符号说明 先明确几个常用的格式符号含义:
#:表示任意数字,不存在则不显示(例如格式#.##,数字 1.2 会显示为1.2,而非1.20); ,:千分位分隔符(每三位数字分隔,如 1234567 会显示为1,234,567); .:小数点分隔符,用于区分整数部分和小数部分; 0:表示数字,不存在则补 0(例如格式0.00,数字 1.2 会显示为1.20)。 2. 示例:格式化大额数字与固定小数位 代码示例:
import java.text.DecimalFormat;
public class Main2 { public static void main(String[] args) { // 定义格式:千分位分隔,保留4位小数 DecimalFormat decimalFormat = new DecimalFormat("###,###.0000"); // 格式化数字12553456.598795 System.out.println(decimalFormat.format(12553456.598795)); } } AI写代码 java 运行
输出结果: 12,553,456.5988
解析:
格式###,###.0000中,###,###表示整数部分每三位用逗号分隔(千分位); .0000表示小数部分固定保留 4 位,不足则补 0,超出则四舍五入(原数字小数位是598795,四舍五入后为5988)。 3. 更多格式化场景示例 除了示例中的格式,DecimalFormat还支持多种实用格式,举例如下:
public class DecimalFormatDemo { public static void main(String[] args) { // 1. 整数部分补0(如固定3位整数,不足补0) DecimalFormat df1 = new DecimalFormat("000"); System.out.println(df1.format(5)); // 输出:005
csharp
// 2. 保留2位小数,整数部分千分位
DecimalFormat df2 = new DecimalFormat("###,###.00");
System.out.println(df2.format(123456.7)); // 输出:123,456.70
// 3. 百分比格式(数字×100后加%)
DecimalFormat df3 = new DecimalFormat("0.00%");
System.out.println(df3.format(0.356)); // 输出:35.60%
// 4. 科学计数法(保留2位小数)
DecimalFormat df4 = new DecimalFormat("0.00E0");
System.out.println(df4.format(123456)); // 输出:1.23E5(即1.23×10^5)
}
} AI写代码 java 运行
核心总结:DecimalFormat的关键是通过格式模式字符串定义规则,其中#和0用于控制数字位数(0强制补 0,#不强制),,用于千分位,.用于分隔整数和小数部分。
二、BigDecimal:高精度数值计算类 float和double是 Java 中的基本浮点类型,但由于二进制存储的特性,它们无法精确表示所有十进制小数(例如0.1用 double 存储时实际是近似值),在金融、电商等对精度要求极高的场景中会导致误差(如金额计算错误)。
BigDecimal是java.math包下的类,支持任意精度的数值计算,完美解决浮点精度问题。
- 为什么需要 BigDecimal? 先看一个反例:用double计算 0.1+0.2 的结果:
System.out.println(0.1 + 0.2); // 输出:0.30000000000000004(存在精度误差) AI写代码 java 运行 这是因为0.1和0.2在二进制中无法精确表示,累加后误差被放大。而BigDecimal可以避免这种问题:
import java.math.BigDecimal;
public class BigDecimalDemo { public static void main(String[] args) { BigDecimal a = new BigDecimal("0.1"); BigDecimal b = new BigDecimal("0.2"); System.out.println(a.add(b)); // 输出:0.3(精确计算) } } AI写代码 java 运行 2. 基本用法:创建与运算 BigDecimal的创建和加法运算:
// 创建BigDecimal对象(注意:不推荐用double构造,原因见下文) BigDecimal bigDecimal = new BigDecimal(1.555555555555555); BigDecimal bigDecimal1 = new BigDecimal(2.999999999999); // 加法运算 System.out.println(bigDecimal.add(bigDecimal1)); AI写代码 java 运行 输出结果(可能存在误差): 4.555555555554555
这里有个坑:用double作为参数构造BigDecimal时,由于double本身的精度问题,BigDecimal会保留其近似值,导致计算结果仍有误差。推荐用String作为构造参数,确保精度:
// 正确写法:用String构造 BigDecimal a = new BigDecimal("1.555555555555555"); BigDecimal b = new BigDecimal("2.999999999999"); System.out.println(a.add(b)); // 输出:4.555555555554555(精确) AI写代码 java 运行 3. 常用运算方法 BigDecimal提供了丰富的运算方法,支持加减乘除等操作,注意运算后需用变量接收结果(BigDecimal是不可变类,运算不会修改原对象):
java
public class BigDecimalOperation {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3");
// 加法
BigDecimal sum = a.add(b);
System.out.println("和:" + sum); // 输出:13.5
// 减法
BigDecimal sub = a.subtract(b);
System.out.println("差:" + sub); // 输出:7.5
// 乘法
BigDecimal mul = a.multiply(b);
System.out.println("积:" + mul); // 输出:31.5
// 除法(需指定保留小数位和舍入模式,避免除不尽报错)
BigDecimal div = a.divide(b, 2, BigDecimal.ROUND_HALF_UP);
// 解释:divide(除数, 保留小数位数, 舍入模式)
// ROUND_HALF_UP:四舍五入
System.out.println("商:" + div); // 输出:3.50
}
}
除法注意事项:当除数不能整除被除数时(如 10.5÷3=3.5,但若 10÷3 则是无限循环),必须指定保留小数位数和舍入模式,否则会抛出ArithmeticException。常用舍入模式:
ROUND_HALF_UP:四舍五入(最常用); ROUND_DOWN:直接舍去多余小数(截断); ROUND_UP:向上进 1(无论小数位是否大于 0)。
三、注意事项与最佳实践
1. DecimalFormat 的线程安全性
DecimalFormat是非线程安全的(内部有可变状态),多线程环境下若共享同一个DecimalFormat实例,可能导致格式化结果错乱。解决方式:
- 每个线程创建独立的DecimalFormat实例;
- 用ThreadLocal封装,确保线程私有。
2. BigDecimal 的构造方法选择
尽量避免用double构造BigDecimal(如new BigDecimal(0.1)),因为double本身精度有误差。推荐用String构造(new BigDecimal("0.1")),或使用BigDecimal.valueOf(double)(内部会先转为 String,减少误差)。
3. BigDecimal 的比较大小
不能用==或equals()比较BigDecimal的值(equals()会同时比较值和精度,如new BigDecimal("1.0").equals(new BigDecimal("1"))返回false)。正确方式是用compareTo:
java
BigDecimal x = new BigDecimal("1.0");
BigDecimal y = new BigDecimal("1");
System.out.println(x.compareTo(y) == 0); // 输出:true(表示相等)
// compareTo返回值:0(相等)、1(x>y)、-1(x<y)
4. 适用场景区分
- DecimalFormat:用于数字的格式化展示(如界面显示金额、报表数据);
- BigDecimal:用于高精度数值计算(如金融交易、金额累加、税率计算)。