本文目录导读:

我将为您提供几个Java金额计算的完整案例,涵盖常见的业务场景和最佳实践。
基础金额计算(使用BigDecimal)
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BasicAmountCalculation {
public static void main(String[] args) {
// 商品价格
BigDecimal price = new BigDecimal("199.99");
int quantity = 3;
// 计算总价
BigDecimal totalPrice = calculateTotalPrice(price, quantity);
System.out.println("商品单价: " + price + " 元");
System.out.println("购买数量: " + quantity + " 件");
System.out.println("商品总价: " + totalPrice + " 元");
// 计算折扣后的价格
BigDecimal discountRate = new BigDecimal("0.85"); // 85折
BigDecimal discountedPrice = applyDiscount(totalPrice, discountRate);
System.out.println("折扣后金额: " + discountedPrice + " 元");
// 计算税费(10%税率)
BigDecimal taxRate = new BigDecimal("0.10");
BigDecimal taxAmount = calculateTax(discountedPrice, taxRate);
System.out.println("税费金额: " + taxAmount + " 元");
// 最终应付金额
BigDecimal finalAmount = discountedPrice.add(taxAmount);
System.out.println("最终应付: " + finalAmount + " 元");
}
/**
* 计算总价
*/
public static BigDecimal calculateTotalPrice(BigDecimal price, int quantity) {
return price.multiply(BigDecimal.valueOf(quantity))
.setScale(2, RoundingMode.HALF_UP);
}
/**
* 应用折扣
*/
public static BigDecimal applyDiscount(BigDecimal amount, BigDecimal discountRate) {
return amount.multiply(discountRate)
.setScale(2, RoundingMode.HALF_UP);
}
/**
* 计算税费
*/
public static BigDecimal calculateTax(BigDecimal amount, BigDecimal taxRate) {
return amount.multiply(taxRate)
.setScale(2, RoundingMode.HALF_UP);
}
}
订单金额计算服务
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
* 订单金额计算服务
*/
public class OrderAmountCalculator {
// 订单项
static class OrderItem {
private String productName;
private BigDecimal unitPrice;
private int quantity;
private BigDecimal discountRate; // 单项折扣,1.0表示无折扣
public OrderItem(String productName, BigDecimal unitPrice, int quantity) {
this(productName, unitPrice, quantity, new BigDecimal("1.0"));
}
public OrderItem(String productName, BigDecimal unitPrice, int quantity, BigDecimal discountRate) {
this.productName = productName;
this.unitPrice = unitPrice;
this.quantity = quantity;
this.discountRate = discountRate;
}
public BigDecimal getSubtotal() {
return unitPrice.multiply(BigDecimal.valueOf(quantity))
.multiply(discountRate)
.setScale(2, RoundingMode.HALF_UP);
}
}
static class Order {
private List<OrderItem> items;
private BigDecimal shippingFee;
private BigDecimal taxRate;
public Order() {
this.items = new ArrayList<>();
this.shippingFee = new BigDecimal("0");
this.taxRate = new BigDecimal("0.10"); // 10% 税率
}
public void addItem(OrderItem item) {
items.add(item);
}
public void setShippingFee(BigDecimal shippingFee) {
this.shippingFee = shippingFee;
}
// 商品总金额
public BigDecimal getItemsTotal() {
BigDecimal total = BigDecimal.ZERO;
for (OrderItem item : items) {
total = total.add(item.getSubtotal());
}
return total.setScale(2, RoundingMode.HALF_UP);
}
// 免运费门槛判断(通常满100免运费)
public boolean isFreeShipping() {
return getItemsTotal().compareTo(new BigDecimal("100")) >= 0;
}
// 实际运费
public BigDecimal getActualShippingFee() {
if (isFreeShipping()) {
return BigDecimal.ZERO;
}
return shippingFee;
}
// 税费
public BigDecimal getTax() {
return getItemsTotal().multiply(taxRate)
.setScale(2, RoundingMode.HALF_UP);
}
// 订单总额
public BigDecimal getGrandTotal() {
return getItemsTotal()
.add(getActualShippingFee())
.add(getTax())
.setScale(2, RoundingMode.HALF_UP);
}
// 打印订单详情
public void printOrderDetails() {
System.out.println("========== 订单详情 ==========");
for (OrderItem item : items) {
System.out.printf("%s x%d = %.2f元%n",
item.productName,
item.quantity,
item.getSubtotal());
}
System.out.println("------------------------------");
System.out.println("商品总金额: " + getItemsTotal() + " 元");
System.out.println("运费: " + getActualShippingFee() + " 元");
System.out.println("税费(10%): " + getTax() + " 元");
System.out.println("订单总额: " + getGrandTotal() + " 元");
}
}
public static void main(String[] args) {
// 创建订单
Order order = new Order();
// 添加商品
order.addItem(new OrderItem("iPhone 15", new BigDecimal("6999.00"), 1));
order.addItem(new OrderItem("手机壳", new BigDecimal("49.90"), 2, new BigDecimal("0.95")));
order.addItem(new OrderItem("钢化膜", new BigDecimal("19.90"), 3));
// 设置运费
order.setShippingFee(new BigDecimal("10.00"));
// 打印订单详情
order.printOrderDetails();
}
}
分期付款计算器
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
* 分期付款计算器
*/
public class InstallmentCalculator {
static class InstallmentPlan {
private BigDecimal principal; // 本金
private BigDecimal annualRate; // 年利率
private int months; // 分期期数
private BigDecimal monthlyRate; // 月利率
public InstallmentPlan(BigDecimal principal, BigDecimal annualRate, int months) {
this.principal = principal;
this.annualRate = annualRate;
this.months = months;
this.monthlyRate = annualRate.divide(new BigDecimal("12"), 10, RoundingMode.HALF_UP);
}
// 等额本息每月还款额
public BigDecimal getMonthlyPayment() {
if (months == 0) return principal;
// 公式: 每月还款 = P * r * (1+r)^n / ((1+r)^n - 1)
BigDecimal monthlyRate = this.monthlyRate;
// 计算 (1+r)^n
BigDecimal power = BigDecimal.ONE;
for (int i = 0; i < months; i++) {
power = power.multiply(BigDecimal.ONE.add(monthlyRate));
}
// 分子: P * r * (1+r)^n
BigDecimal numerator = principal
.multiply(monthlyRate)
.multiply(power);
// 分母: (1+r)^n - 1
BigDecimal denominator = power.subtract(BigDecimal.ONE);
return numerator.divide(denominator, 2, RoundingMode.HALF_UP);
}
// 总还款额
public BigDecimal getTotalPayment() {
return getMonthlyPayment().multiply(BigDecimal.valueOf(months))
.setScale(2, RoundingMode.HALF_UP);
}
// 总利息
public BigDecimal getTotalInterest() {
return getTotalPayment().subtract(principal)
.setScale(2, RoundingMode.HALF_UP);
}
// 生成还款计划表
public List<PaymentDetail> getPaymentSchedule() {
List<PaymentDetail> schedule = new ArrayList<>();
BigDecimal remainingBalance = principal;
BigDecimal monthlyPayment = getMonthlyPayment();
for (int month = 1; month <= months; month++) {
BigDecimal interest = remainingBalance
.multiply(monthlyRate)
.setScale(2, RoundingMode.HALF_UP);
BigDecimal principalPart = monthlyPayment.subtract(interest);
BigDecimal previousBalance = remainingBalance;
remainingBalance = remainingBalance.subtract(principalPart)
.max(BigDecimal.ZERO);
schedule.add(new PaymentDetail(month, monthlyPayment, principalPart,
interest, previousBalance, remainingBalance));
}
return schedule;
}
// 打印计划
public void printSchedule() {
System.out.println("===== 分期付款计划 =====");
System.out.println("本金: " + principal + " 元");
System.out.println("年利率: " + annualRate.multiply(new BigDecimal("100")) + "%");
System.out.println("分期期数: " + months + " 个月");
System.out.println("每月还款: " + getMonthlyPayment() + " 元");
System.out.println("总利息: " + getTotalInterest() + " 元");
System.out.println("总还款: " + getTotalPayment() + " 元");
System.out.println();
System.out.println("--- 还款明细 ---");
System.out.printf("%-6s %-12s %-12s %-12s %-12s %-12s%n",
"期数", "月还款额", "本金", "利息", "剩余本金", "上期余额");
for (PaymentDetail detail : getPaymentSchedule()) {
System.out.printf("%-6d %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f%n",
detail.month, detail.payment, detail.principal, detail.interest,
detail.balance, detail.previousBalance);
}
}
}
// 还款明细类
static class PaymentDetail {
int month;
BigDecimal payment; // 月还款额
BigDecimal principal; // 本金部分
BigDecimal interest; // 利息部分
BigDecimal previousBalance; // 上期剩余本金
BigDecimal balance; // 本期剩余本金
public PaymentDetail(int month, BigDecimal payment, BigDecimal principal,
BigDecimal interest, BigDecimal previousBalance, BigDecimal balance) {
this.month = month;
this.payment = payment;
this.principal = principal;
this.interest = interest;
this.previousBalance = previousBalance;
this.balance = balance;
}
}
public static void main(String[] args) {
// 贷款10000元,年利率5%,分12期
InstallmentPlan plan = new InstallmentPlan(
new BigDecimal("10000.00"),
new BigDecimal("0.05"),
12
);
plan.printSchedule();
}
}
汇率转换器
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
/**
* 汇率转换器
*/
public class CurrencyConverter {
private Map<String, Map<String, BigDecimal>> exchangeRates;
public CurrencyConverter() {
exchangeRates = new HashMap<>();
initRates();
}
private void initRates() {
// 以人民币(CNY)为基准的汇率
Map<String, BigDecimal> cnyRates = new HashMap<>();
cnyRates.put("USD", new BigDecimal("0.139")); // 1 CNY = 0.139 USD
cnyRates.put("EUR", new BigDecimal("0.128")); // 1 CNY = 0.128 EUR
cnyRates.put("GBP", new BigDecimal("0.110")); // 1 CNY = 0.110 GBP
cnyRates.put("JPY", new BigDecimal("20.500")); // 1 CNY = 20.5 JPY
exchangeRates.put("CNY", cnyRates);
}
/**
* 货币转换
* @param amount 金额
* @param fromCurrency 源货币
* @param toCurrency 目标货币
* @return 转换后的金额
*/
public BigDecimal convert(BigDecimal amount, String fromCurrency, String toCurrency) {
if (fromCurrency.equals(toCurrency)) {
return amount.setScale(2, RoundingMode.HALF_UP);
}
// 先转换为人民币
BigDecimal amountInCNY;
if (fromCurrency.equals("CNY")) {
amountInCNY = amount;
} else {
// 从其他货币转到人民币,需要倒数
Map<String, BigDecimal> cnyRates = exchangeRates.get("CNY");
BigDecimal rate = cnyRates.get(fromCurrency);
amountInCNY = amount.divide(rate, 10, RoundingMode.HALF_UP);
}
// 从人民币转换为目标货币
Map<String, BigDecimal> cnyRates = exchangeRates.get("CNY");
BigDecimal targetRate = cnyRates.get(toCurrency);
if (targetRate == null) {
throw new IllegalArgumentException("不支持的货币: " + toCurrency);
}
return amountInCNY.multiply(targetRate)
.setScale(2, RoundingMode.HALF_UP);
}
public static void main(String[] args) {
CurrencyConverter converter = new CurrencyConverter();
// 转换示例
BigDecimal amountInCNY = new BigDecimal("1000.00");
System.out.println("1000人民币转换结果:");
System.out.println("美元(USD): " + converter.convert(amountInCNY, "CNY", "USD"));
System.out.println("欧元(EUR): " + converter.convert(amountInCNY, "CNY", "EUR"));
System.out.println("英镑(GBP): " + converter.convert(amountInCNY, "CNY", "GBP"));
System.out.println("日元(JPY): " + converter.convert(amountInCNY, "CNY", "JPY"));
// 逆转换
BigDecimal usdAmount = converter.convert(amountInCNY, "CNY", "USD");
System.out.println("\n1000美元转换回人民币: " +
converter.convert(usdAmount, "USD", "CNY"));
}
}
金额工具类(最佳实践)
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Currency;
import java.util.Locale;
/**
* 金额工具类 - 企业级金额处理规范
*/
public final class AmountUtil {
private static final int DEFAULT_SCALE = 2;
private static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_UP;
private static final BigDecimal ONE_HUNDRED = new BigDecimal("100");
private AmountUtil() {
// 私有构造函数,防止实例化
}
/**
* 创建安全的BigDecimal金额
*/
public static BigDecimal createAmount(String value) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException("金额不能为空");
}
return new BigDecimal(value).setScale(DEFAULT_SCALE, DEFAULT_ROUNDING);
}
/**
* 金额累加
*/
public static BigDecimal add(BigDecimal... amounts) {
BigDecimal result = BigDecimal.ZERO;
for (BigDecimal amount : amounts) {
if (amount != null) {
result = result.add(amount);
}
}
return result.setScale(DEFAULT_SCALE, DEFAULT_ROUNDING);
}
/**
* 金额相减
*/
public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend) {
if (minuend == null || subtrahend == null) {
throw new IllegalArgumentException("金额不能为null");
}
return minuend.subtract(subtrahend).setScale(DEFAULT_SCALE, DEFAULT_ROUNDING);
}
/**
* 金额乘法
*/
public static BigDecimal multiply(BigDecimal amount, BigDecimal multiplier) {
if (amount == null || multiplier == null) {
throw new IllegalArgumentException("参数不能为null");
}
return amount.multiply(multiplier).setScale(DEFAULT_SCALE, DEFAULT_ROUNDING);
}
/**
* 金额除法
*/
public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor) {
if (dividend == null || divisor == null) {
throw new IllegalArgumentException("参数不能为null");
}
if (divisor.compareTo(BigDecimal.ZERO) == 0) {
throw new ArithmeticException("除数不能为零");
}
return dividend.divide(divisor, DEFAULT_SCALE, DEFAULT_ROUNDING);
}
/**
* 百分比转换(金额 * 百分数值)
*/
public static BigDecimal percent(BigDecimal amount, BigDecimal percent) {
if (percent == null || percent.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("百分比必须为非负数");
}
return amount.multiply(percent)
.divide(ONE_HUNDRED, DEFAULT_SCALE, DEFAULT_ROUNDING);
}
/**
* 安全比较金额大小
*/
public static int compare(BigDecimal amount1, BigDecimal amount2) {
if (amount1 == null || amount2 == null) {
throw new IllegalArgumentException("金额不能为null");
}
return amount1.compareTo(amount2);
}
/**
* 是否相等
*/
public static boolean equals(BigDecimal amount1, BigDecimal amount2) {
return amount1 != null && amount2 != null &&
amount1.compareTo(amount2) == 0;
}
/**
* 金额格式化(带货币符号)
*/
public static String formatCurrency(BigDecimal amount, Locale locale) {
if (amount == null) {
return "";
}
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(locale);
return currencyFormat.format(amount.doubleValue());
}
/**
* 金额格式化(不带货币符号,千分位)
*/
public static String formatNumber(BigDecimal amount) {
if (amount == null) {
return "0.00";
}
DecimalFormat df = new DecimalFormat("#,##0.00");
return df.format(amount);
}
/**
* 转换为人民币大写金额
*/
public static String toChineseRMB(BigDecimal amount) {
if (amount == null || amount.compareTo(BigDecimal.ZERO) == 0) {
return "零元整";
}
if (amount.compareTo(BigDecimal.ZERO) < 0) {
return "负" + toChineseRMB(amount.abs());
}
String[] digits = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
String[] units = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿"};
String result = "";
// 分离整数和小数部分
BigDecimal scaledAmount = amount.setScale(2, RoundingMode.HALF_UP);
String[] parts = scaledAmount.toString().split("\\.");
String integerPart = parts[0];
String decimalPart = parts.length > 1 ? parts[1] : "";
// 转换整数部分
int intLength = integerPart.length();
for (int i = 0; i < intLength; i++) {
int digit = integerPart.charAt(i) - '0';
int unitIndex = intLength - i - 1;
if (digit != 0) {
result += digits[digit] + units[unitIndex];
} else if (i > 0 && integerPart.charAt(i - 1) != '0' &&
units[unitIndex].length() > 0) {
result += "零";
}
}
result += "元";
// 转换小数部分
if (decimalPart.length() > 0) {
int jiao = decimalPart.charAt(0) - '0';
if (jiao > 0) {
result += digits[jiao] + "角";
}
if (decimalPart.length() > 1) {
int fen = decimalPart.charAt(1) - '0';
if (fen > 0) {
result += digits[fen] + "分";
}
}
}
if (!result.contains("角") && !result.contains("分")) {
result += "整";
}
return result;
}
/**
* 测试
*/
public static void main(String[] args) {
// 测试金额计算
BigDecimal price = AmountUtil.createAmount("199.99");
BigDecimal quantity = new BigDecimal("3");
BigDecimal total = AmountUtil.multiply(price, quantity);
System.out.println("商品总价: " + AmountUtil.formatNumber(total));
System.out.println("含税金额(13%): " +
AmountUtil.formatNumber(AmountUtil.add(total, AmountUtil.percent(total, new BigDecimal("13")))));
// 测试人民币大写
BigDecimal amount = new BigDecimal("12345.67");
System.out.println("\n金额: " + amount);
System.out.println("人民币大写: " + AmountUtil.toChineseRMB(amount));
// 测试格式化
System.out.println("\n格式化示例:");
System.out.println("¥: " + AmountUtil.formatCurrency(amount, Locale.CHINA));
System.out.println("$: " + AmountUtil.formatCurrency(amount, Locale.US));
}
}
使用BigDecimal而非double/float
double和float存在精度问题- 所有金额计算必须使用
BigDecimal
设置合适的精度和舍入模式
BigDecimal amount = new BigDecimal("10.005")
.setScale(2, RoundingMode.HALF_UP); // 四舍五入
使用字符串构造BigDecimal
// 正确方式
BigDecimal amount = new BigDecimal("19.99");
// 错误方式(可能产生精度问题)
BigDecimal amount = new BigDecimal(19.99);
金额比较使用compareTo
// 正确方式 amount1.compareTo(amount2) == 0; // 错误方式(可能不准确) amount1.equals(amount2);
常见金额场景处理
- 下单计算:包含商品金额、运费、折扣、税费
- 支付处理:金额验证、支付成功金额核对
- 退款处理:原路退回,计算手续费
- 账户余额:存、取、利息计算
这些示例涵盖了Java金额计算的主要场景,您可以根据实际需求进行调整和扩展。