在Java开发中,处理double类型的小数截断需求十分常见,尤其是需要保留指定位数且不进行四舍五入的场景,比如金额计算、统计数据展示等场景,错误的四舍五入可能会导致数据偏差。下面介绍几种可靠的实现方式。

使用Math.floor方法实现
Math类的floor方法会返回小于等于参数的最大整数,我们可以利用这个特性先对double值乘以100,再取floor,最后除以100,就能实现截断小数点后两位的效果。
public class DoubleTruncateDemo {
public static void main(String[] args) {
double num = 3.1415926;
// 先乘以100,再取floor,最后除以100
double result = Math.floor(num * 100) / 100;
System.out.println(result); // 输出3.14
}
}
这种方法的优点是逻辑简单,不需要引入额外的类,但是要注意double类型本身的精度问题,当数值过大时可能会出现精度丢失的情况。
使用BigDecimal实现
BigDecimal是Java中用于处理高精度小数的类,通过它可以更精准地控制小数位的截断操作,避免double自带的精度误差。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalTruncateDemo {
public static void main(String[] args) {
double num = 3.14999;
// 将double转换为BigDecimal,注意要使用字符串构造器避免精度问题
BigDecimal bd = new BigDecimal(String.valueOf(num));
// 设置保留两位,截断模式使用DOWN,即直接丢弃多余位数
BigDecimal resultBd = bd.setScale(2, RoundingMode.DOWN);
double result = resultBd.doubleValue();
System.out.println(result); // 输出3.14
}
}
这里需要注意,构造BigDecimal时不要直接使用double作为参数,否则会继承double的精度误差,使用字符串构造可以保证数值的准确性。RoundingMode.DOWN就是直接截断不进位,符合我们的需求。
字符串处理方式
如果不需要进行后续的数值计算,只是需要展示截断后的结果,也可以通过字符串截取的方式实现。
public class StringTruncateDemo {
public static void main(String[] args) {
double num = 3.1415926;
String numStr = String.valueOf(num);
int dotIndex = numStr.indexOf(".");
if (dotIndex != -1) {
// 如果小数点后位数大于等于2,截取前两位
if (numStr.length() - dotIndex - 1 >= 2) {
numStr = numStr.substring(0, dotIndex + 3);
}
}
System.out.println(numStr); // 输出3.14
}
}
这种方式的局限性比较大,只能得到字符串形式的结果,如果需要转回double类型,还是可能遇到精度问题,适合仅用于展示的场景。
不同方法对比
我们可以通过下面的表格对比几种方法的优缺点,方便选择:
| 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Math.floor | 逻辑简单,无额外依赖 | 存在double精度误差风险 | 数值较小,对精度要求不高的场景 |
| BigDecimal | 精度高,可控性强 | 代码稍复杂,需要额外引入类 | 金额计算等对精度要求高的场景 |
| 字符串处理 | 实现简单,无精度问题 | 只能得到字符串,无法用于数值计算 | 仅用于前端展示的场景 |
注意事项
- 如果使用Math.floor方法,当处理负数时,比如-3.1415,乘以100后是-314.15,floor之后是-315,除以100得到-3.15,如果需要负数的截断逻辑是保留两位后直接丢弃后面的位数(即-3.14),则需要额外处理负数的情况。
- BigDecimal的setScale方法如果设置的保留位数小于原有小数位数,必须使用RoundingMode参数,否则会抛出ArithmeticException异常。
- 无论使用哪种方式,都要明确自己的业务需求,确认是需要截断还是四舍五入,避免逻辑错误。
如果需要处理负数的截断且要求截断后是-3.14这样的结果,可以在Math.floor方法前先判断数值正负,正数正常处理,负数先取绝对值处理后再加回负号。
public static double truncateDouble(double num) {
if (num >= 0) {
return Math.floor(num * 100) / 100;
} else {
return -Math.floor(Math.abs(num) * 100) / 100;
}
}
Javadouble截断小数Math_floor修改时间:2026-06-20 04:21:27