用字符串构造 bigdecimal,将单价乘以数量和折扣系数,最后用 setscale(2, roundingmode.half_up) 保留两位小数。示例按订单总额舍入,逐行结算时应按业务约定调整舍入时点。

从十进制文本构造单价和折扣
在 JDK 17 或更高版本中,将示例保存为 DiscountDemo.java。折扣系数 0.85 表示按原价的 85% 结算。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class DiscountDemo {
public static void main(String[] args) {
BigDecimal price = new BigDecimal("19.99");
BigDecimal quantity = BigDecimal.valueOf(3);
BigDecimal factor = new BigDecimal("0.85");
BigDecimal raw = price.multiply(quantity).multiply(factor);
BigDecimal total = raw.setScale(2, RoundingMode.HALF_UP);
System.out.println(raw.toPlainString());
System.out.println(total.toPlainString());
}
}

执行 java DiscountDemo.java,预期输出 50.9745 和 50.97。BigDecimal 是不可变对象,必须接住 setScale 的返回值。
比较逐件舍入与总额舍入
在 main 方法里追加这段对照。
BigDecimal roundedUnit = price.multiply(factor)
.setScale(2, RoundingMode.HALF_UP);
System.out.println(roundedUnit.multiply(quantity).toPlainString());
逐件先取两位的结果是 50.97。本组数据恰好相同,可以把单价改为 19.98 再观察,总额舍入结果为 50.95,逐件先舍入为 50.94。
需要传整数分时做精确转换
把已经按结算规则处理的总额转成分,并检查能否由 long 表示。
long cents = total.movePointRight(2).longValueExact(); System.out.println(cents);
原始示例得到 5097。超出 long 表示范围或仍有非零小数时,longValueExact 会抛出 ArithmeticException。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











