本文目录导读:

在Java中避免浮点型精度差的常用方法有以下几种:
使用 BigDecimal 类(推荐)
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalExample {
public static void main(String[] args) {
// 使用字符串构造,避免精度问题
BigDecimal num1 = new BigDecimal("0.1");
BigDecimal num2 = new BigDecimal("0.2");
// 加法
BigDecimal sum = num1.add(num2);
System.out.println("0.1 + 0.2 = " + sum); // 输出: 0.3
// 减法
BigDecimal diff = num1.subtract(num2);
// 乘法
BigDecimal product = num1.multiply(num2);
// 除法(需要指定精度和舍入模式)
BigDecimal quotient = num1.divide(num2, 10, RoundingMode.HALF_UP);
// 设置精度
BigDecimal result = new BigDecimal("10.12345");
result = result.setScale(2, RoundingMode.HALF_UP);
System.out.println("保留2位小数: " + result); // 输出: 10.12
}
}
货币计算使用整型(分/厘为单位)
public class CurrencyExample {
public static void main(String[] args) {
// 以分为单位存储
long priceInCents = 1099; // 10.99元
// 显示时转换
double displayPrice = priceInCents / 100.0;
System.out.println("价格: " + displayPrice + "元");
// 计算时用整型
long quantity = 3;
long totalInCents = priceInCents * quantity;
System.out.println("总价: " + totalInCents / 100.0 + "元");
}
}
使用 Math 类的方法(简单场景)
public class MathExample {
public static void main(String[] args) {
double value = 3.1415926;
// 四舍五入到指定小数位
double rounded = Math.round(value * 100.0) / 100.0;
System.out.println("四舍五入到2位小数: " + rounded);
// 向上取整
double ceil = Math.ceil(value * 100) / 100;
System.out.println("向上取整到2位小数: " + ceil);
// 向下取整
double floor = Math.floor(value * 100) / 100;
System.out.println("向下取整到2位小数: " + floor);
}
}
比较浮点数时的正确处理
public class CompareExample {
public static void main(String[] args) {
double a = 0.1 + 0.2;
double b = 0.3;
// 错误方式
System.out.println(a == b); // false
// 正确方式:使用误差范围
double epsilon = 1e-10;
System.out.println(Math.abs(a - b) < epsilon); // true
// 使用 BigDecimal 比较
BigDecimal bd1 = new BigDecimal("0.1").add(new BigDecimal("0.2"));
BigDecimal bd2 = new BigDecimal("0.3");
System.out.println(bd1.compareTo(bd2) == 0); // true
}
}
完整的实用工具类
import java.math.BigDecimal;
import java.math.RoundingMode;
public class DecimalUtil {
// 默认精度
private static final int DEFAULT_SCALE = 2;
// 安全创建 BigDecimal
public static BigDecimal create(String value) {
return new BigDecimal(value);
}
// 安全加法
public static BigDecimal add(String v1, String v2) {
return new BigDecimal(v1).add(new BigDecimal(v2));
}
// 安全减法
public static BigDecimal subtract(String v1, String v2) {
return new BigDecimal(v1).subtract(new BigDecimal(v2));
}
// 安全乘法
public static BigDecimal multiply(String v1, String v2) {
return new BigDecimal(v1).multiply(new BigDecimal(v2));
}
// 安全除法
public static BigDecimal divide(String v1, String v2, int scale) {
return new BigDecimal(v1).divide(new BigDecimal(v2), scale, RoundingMode.HALF_UP);
}
// 格式化输出
public static String format(BigDecimal value) {
return value.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP).toString();
}
// 使用示例
public static void main(String[] args) {
String result = format(add("0.1", "0.2"));
System.out.println("0.1 + 0.2 = " + result); // 输出: 0.30
}
}
- 财务计算:始终使用
BigDecimal,并用字符串构造 - 普通业务逻辑:使用整型(如分为单位)
- 性能要求高:使用
double+误差比较 - 数据库存储:使用
DECIMAL类型 - API 返回值:使用字符串类型传输精确值
永远不要使用 比较浮点数,使用 BigDecimal.compareTo() 或误差范围比较。