数学工具
MathUtils 提供精确数学计算和常用数学操作。
类信息
- 包名:
com.molandev.framework.util - 类名:
MathUtils - 类型: 静态工具类
使用场景
- ✅ 金额计算(避免精度丢失)
- ✅ 统计计算
- ✅ 浮点数比较
- ✅ 数值处理
核心方法
add - 精确加法
java
public static double add(double v1, double v2)示例:
java
double result = MathUtils.add(0.1, 0.2);
// 0.3 (而不是 0.30000000000000004)sub - 精确减法
java
public static double sub(double v1, double v2)示例:
java
double result = MathUtils.sub(1.0, 0.9);
// 0.1 (精确结果)mul - 精确乘法
java
public static double mul(double v1, double v2)示例:
java
double result = MathUtils.mul(0.1, 0.2);
// 0.02div - 精确除法
java
public static double div(double v1, double v2)
public static double div(double v1, double v2, int scale)参数:
scale: 保留小数位(默认10位)
示例:
java
double result = MathUtils.div(10, 3); // 3.3333333333
double result2 = MathUtils.div(10, 3, 2); // 3.33round - 四舍五入
java
public static double round(double v, int scale)示例:
java
double rounded = MathUtils.round(3.1415926, 2); // 3.14
double rounded2 = MathUtils.round(3.1415926, 4); // 3.1416min / max - 最小值/最大值
java
public static int min(int... nums)
public static int max(int... nums)示例:
java
int min = MathUtils.min(5, 2, 8, 1, 9); // 1
int max = MathUtils.max(5, 2, 8, 1, 9); // 9equals - 浮点数相等比较
java
public static boolean equals(double a, double b)
public static boolean equals(double a, double b, double scale)示例:
java
boolean eq = MathUtils.equals(0.1 + 0.2, 0.3); // true
boolean eq2 = MathUtils.equals(3.14, 3.15, 0.1); // true(允许误差0.1)完整示例
示例 1:金额计算
java
import com.molandev.framework.util.MathUtils;
public class PriceCalculator {
/**
* 计算订单总价
*/
public static double calculateTotal(double price, int quantity, double discount) {
// 单价 × 数量
double subtotal = MathUtils.mul(price, quantity);
// 应用折扣
double discountAmount = MathUtils.mul(subtotal, discount);
// 总价
double total = MathUtils.sub(subtotal, discountAmount);
// 保留2位小数
return MathUtils.round(total, 2);
}
public static void main(String[] args) {
double price = 99.99;
int quantity = 3;
double discount = 0.15; // 15%折扣
double total = calculateTotal(price, quantity, discount);
System.out.println("总价: " + total); // 254.97
}
}示例 2:税费计算
java
import com.molandev.framework.util.MathUtils;
public class TaxCalculator {
private static final double TAX_RATE = 0.06; // 6%税率
public static double calculateWithTax(double amount) {
double tax = MathUtils.mul(amount, TAX_RATE);
double total = MathUtils.add(amount, tax);
return MathUtils.round(total, 2);
}
public static void main(String[] args) {
double amount = 100.00;
double withTax = calculateWithTax(amount);
System.out.println("含税价: " + withTax); // 106.00
}
}示例 3:平均分配
java
import com.molandev.framework.util.MathUtils;
public class Allocator {
/**
* 平均分配金额
*/
public static double[] allocate(double total, int parts) {
double[] result = new double[parts];
double perPart = MathUtils.div(total, parts, 2);
// 分配
for (int i = 0; i < parts - 1; i++) {
result[i] = perPart;
}
// 最后一份用总额减去已分配的(避免精度损失)
double allocated = MathUtils.mul(perPart, parts - 1);
result[parts - 1] = MathUtils.sub(total, allocated);
return result;
}
public static void main(String[] args) {
double[] parts = allocate(100.00, 3);
// [33.33, 33.33, 33.34] 总和正好100.00
for (int i = 0; i < parts.length; i++) {
System.out.println("第" + (i+1) + "份: " + parts[i]);
}
}
}为什么需要 MathUtils?
⚠️ 浮点数精度问题
java
// ❌ 直接计算会有精度问题
System.out.println(0.1 + 0.2); // 0.30000000000000004
System.out.println(1.0 - 0.9); // 0.09999999999999998
// ✅ 使用 MathUtils
System.out.println(MathUtils.add(0.1, 0.2)); // 0.3
System.out.println(MathUtils.sub(1.0, 0.9)); // 0.1⚠️ 金额计算
java
// ❌ 金额计算不要用 double 直接运算
double price = 9.99;
double total = price * 10; // 可能不精确
// ✅ 使用 MathUtils
double total = MathUtils.mul(9.99, 10); // 精确技术细节
所有计算内部使用 BigDecimal,保证精度:
java
// 内部实现示例
public static double add(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.add(b2).doubleValue();
}性能说明
- 速度: 比直接运算慢(因为使用 BigDecimal)
- 精度: 完全精确
- 适用: 金额、税费等要求精确的计算
常见问题
Q: 为什么不直接用 BigDecimal?
A: MathUtils 简化了 BigDecimal 的使用,提供更简洁的API。
Q: 所有场景都要用 MathUtils 吗?
A: 不需要。科学计算、图形学等可以用原生运算。金额计算必须用。