本文目录导读:

我来为您提供几个BigDecimal的实用案例,涵盖常见业务场景:
金额计算场景(电商)
import java.math.BigDecimal;
import java.math.RoundingMode;
public class MoneyCalculation {
public static void main(String[] args) {
// 商品价格
BigDecimal price = new BigDecimal("199.90");
BigDecimal quantity = new BigDecimal("3");
BigDecimal discountRate = new BigDecimal("0.85"); // 85折
// 计算原价
BigDecimal originalPrice = price.multiply(quantity);
System.out.println("原价:" + originalPrice);
// 计算折扣价
BigDecimal discountPrice = originalPrice.multiply(discountRate);
System.out.println("折扣价:" + discountPrice);
// 四舍五入到分(保留2位小数)
BigDecimal finalPrice = discountPrice.setScale(2, RoundingMode.HALF_UP);
System.out.println("最终价格:" + finalPrice);
// 计算税额(13%增值税)
BigDecimal taxRate = new BigDecimal("0.13");
BigDecimal taxAmount = finalPrice.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);
System.out.println("税额:" + taxAmount);
// 含税总价
BigDecimal totalWithTax = finalPrice.add(taxAmount);
System.out.println("含税总价:" + totalWithTax);
}
}
银行账户利息计算
import java.math.BigDecimal;
import java.math.RoundingMode;
public class InterestCalculation {
public static void main(String[] args) {
// 存款本金
BigDecimal principal = new BigDecimal("100000.00");
// 年利率 2.5%
BigDecimal annualRate = new BigDecimal("0.025");
// 存期(年)
int years = 3;
BigDecimal total = principal;
// 复利计算
for (int i = 0; i < years; i++) {
BigDecimal interest = total.multiply(annualRate)
.setScale(2, RoundingMode.HALF_UP);
total = total.add(interest);
System.out.printf("第%d年:利息%s,总额%s%n", i+1, interest, total);
}
// 获取整数部分和小数部分
BigDecimal interestEarned = total.subtract(principal);
BigDecimal intPart = total.toBigInteger().bigDecimalValue();
BigDecimal decPart = total.remainder(BigDecimal.ONE);
System.out.println("总利息:" + interestEarned);
System.out.println("整数部分:" + intPart);
System.out.println("小数部分:" + decPart);
}
}
汇率转换
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
public class CurrencyExchange {
private static Map<String, BigDecimal> exchangeRates = new HashMap<>();
static {
// 币种对美元汇率
exchangeRates.put("USD", new BigDecimal("1.0000"));
exchangeRates.put("CNY", new BigDecimal("7.2450"));
exchangeRates.put("EUR", new BigDecimal("0.9250"));
exchangeRates.put("JPY", new BigDecimal("149.5000"));
}
public static BigDecimal convert(BigDecimal amount, String fromCurrency, String toCurrency) {
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("金额必须大于0");
}
BigDecimal fromRate = exchangeRates.get(fromCurrency);
BigDecimal toRate = exchangeRates.get(toCurrency);
if (fromRate == null || toRate == null) {
throw new IllegalArgumentException("不支持的货币类型");
}
// 转换公式: amount * (toRate / fromRate)
BigDecimal result = amount.multiply(toRate.divide(fromRate, 8, RoundingMode.HALF_UP));
// 保留2位小数,四舍五入
return result.setScale(2, RoundingMode.HALF_UP);
}
public static void main(String[] args) {
// 1000美元兑换人民币
BigDecimal usdAmount = new BigDecimal("1000.00");
BigDecimal cnyResult = convert(usdAmount, "USD", "CNY");
System.out.println("1000美元 = " + cnyResult + "人民币");
// 10000日元兑换欧元
BigDecimal jpyAmount = new BigDecimal("10000");
BigDecimal eurResult = convert(jpyAmount, "JPY", "EUR");
System.out.println("10000日元 = " + eurResult + "欧元");
}
}
精确比较和范围判断
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalComparison {
public static void main(String[] args) {
BigDecimal creditLimit = new BigDecimal("50000.00");
BigDecimal frozenAmount = new BigDecimal("5000.00");
BigDecimal availableAmount = creditLimit.subtract(frozenAmount);
// 业务场景:验证交易金额
BigDecimal transactionAmount = new BigDecimal("45000.00");
// 检查交易金额是否超过可用额度
if (transactionAmount.compareTo(availableAmount) > 0) {
System.out.println("交易金额超限!");
System.out.println("可用额度:" + availableAmount);
System.out.println("交易金额:" + transactionAmount);
} else {
System.out.println("交易成功,可用额度足够");
}
// 检查金额是否在某个范围内
BigDecimal minAmount = new BigDecimal("10.00");
BigDecimal maxAmount = new BigDecimal("1000.00");
// 验证输入金额是否在有效范围内
BigDecimal inputAmount = new BigDecimal("999.99");
boolean inRange = inputAmount.compareTo(minAmount) >= 0
&& inputAmount.compareTo(maxAmount) <= 0;
if (inRange) {
System.out.println("金额在有效范围内");
} else {
System.out.println("金额超出有效范围");
}
// 判断金额是否接近某个值(误差处理)
BigDecimal targetValue = new BigDecimal("100");
BigDecimal actualValue = new BigDecimal("99.99");
BigDecimal tolerance = new BigDecimal("0.05");
BigDecimal diff = actualValue.subtract(targetValue).abs();
if (diff.compareTo(tolerance) <= 0) {
System.out.println("金额在允许误差范围内");
}
}
}
完整的分账系统案例
import java.math.BigDecimal;
import java.math.RoundingMode;
public class SplitAccount {
public static void main(String[] args) {
// 订单总金额
BigDecimal orderTotal = new BigDecimal("1000.00");
// 分账比例设置
BigDecimal platformRate = new BigDecimal("0.20");
BigDecimal merchantRate = new BigDecimal("0.80");
// 计算分账金额(保留2位小数)
BigDecimal platformAmount = orderTotal.multiply(platformRate)
.setScale(2, RoundingMode.HALF_UP);
BigDecimal merchantAmount = orderTotal.multiply(merchantRate)
.setScale(2, RoundingMode.HALF_UP);
System.out.println("订单总额:" + orderTotal);
System.out.println("平台分成(20%):" + platformAmount);
System.out.println("商家分成(80%):" + merchantAmount);
// 验证分账是否完整(可能因为四舍五入有误差)
BigDecimal totalAllocated = platformAmount.add(merchantAmount);
BigDecimal difference = orderTotal.subtract(totalAllocated);
System.out.println("差异金额:" + difference);
// 如果存在差异,调整商家金额(确保总额一致)
if (difference.compareTo(BigDecimal.ZERO) != 0) {
merchantAmount = merchantAmount.add(difference);
System.out.println("调整后商家金额:" + merchantAmount);
System.out.println("调整后分配总额:" + platformAmount.add(merchantAmount));
}
}
}
精度运算注意点
import java.math.BigDecimal;
import java.math.RoundingMode;
public class PrecisionTips {
public static void main(String[] args) {
// 1. 避免使用double构造
BigDecimal wrong1 = new BigDecimal(0.1); // 不精确
BigDecimal correct1 = new BigDecimal("0.1"); // 精确
System.out.println("double构造:" + wrong1);
System.out.println("字符串构造:" + correct1);
// 2. 除以零的处理
BigDecimal number = new BigDecimal("10");
BigDecimal divisor = BigDecimal.ZERO;
try {
number.divide(divisor);
} catch (ArithmeticException e) {
System.out.println("除以零异常:不能将BigDecimal除以0");
}
// 3. 无限小数处理,必须指定精度
BigDecimal numerator = new BigDecimal("1");
BigDecimal denominator = new BigDecimal("3");
// 如果不指定舍入模式会报错
try {
numerator.divide(denominator);
} catch (ArithmeticException e) {
System.out.println("无限小数必须指定精度:" + e.getMessage());
}
// 正确方式
BigDecimal result = numerator.divide(denominator, 4, RoundingMode.HALF_UP);
System.out.println("1/3 = " + result);
// 4. 常量使用
BigDecimal constZero = BigDecimal.ZERO;
BigDecimal constOne = BigDecimal.ONE;
BigDecimal constTen = BigDecimal.TEN;
System.out.println("常用常量:" + constZero + ", " + constOne + ", " + constTen);
}
}
最佳实践建议:
- 构造BigDecimal时使用字符串,避免精度丢失
- 除法运算必须指定精度和舍入模式
- 使用
compareTo()而不是equals()比较大小 - 金额计算保留2位小数(分),使用 HALF_UP 舍入
- 考虑小数位数和精度需求,避免不必要的精度损失
- 存储到数据库时使用
String类型或DECIMAL类型
这些案例覆盖了BigDecimal的主要使用场景,实际开发中可以根据业务需求进行调整和扩展。