You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将VALUE_OF_REAL逻辑转换为Java代码?结果不一致求解

问题

我有如下代码行:VALUE_OF_REAL(#unitPrice, "{#,##0.00}{TR}")。当unitPrice为2.1450000000000000000000000000000时,执行后得到2.145;当unitPrice为271.4050000000000000000000000000000时,执行后得到271.40。我尝试用以下两种Java方式实现,结果都不符合预期:

new DecimalFormat("#,##0.00", localization).format(customer.getUnitPrice().setScale(2, RoundingMode.HALF_UP))
new DecimalFormat("#,##0.00", localization).format(customer.getUnitPrice().setScale(2, RoundingMode.HALF_DOWN))

请解析原函数的工作逻辑,并给出正确的Java实现方案。

原函数逻辑拆解

从给出的输入输出案例,能明确VALUE_OF_REAL结合格式串{#,##0.00}{TR}的规则:

  1. 特殊舍入判断:当数值的小数点后第三位是5,且第三位之后全为0时:
    • 如果小数点后第二位不是0,就保留三位小数(不做两位小数的舍入)
    • 如果小数点后第二位是0,则舍去第三位的5,仅保留两位小数
  2. 末尾零处理:{TR}的作用是去掉小数部分末尾的无效零,但如果舍入后第二位本身就是0(比如271.40),则保留该零。

正确Java实现方案

要完全匹配这个逻辑,需要先对数值做特殊判断,再进行格式化:

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

public class PriceFormatter {
    public static String formatUnitPrice(BigDecimal unitPrice, Locale localization) {
        BigDecimal processedPrice;
        
        // 检查是否是"X.XX5000..."的情况
        BigDecimal scaledTo3 = unitPrice.setScale(3, RoundingMode.DOWN);
        BigDecimal diff = unitPrice.subtract(scaledTo3);
        boolean isThirdDigit5 = diff.compareTo(new BigDecimal("0.005")) == 0;
        
        if (isThirdDigit5) {
            // 获取小数点后第二位数字
            BigDecimal scaledTo2 = unitPrice.setScale(2, RoundingMode.DOWN);
            BigDecimal secondDecimalDigit = scaledTo2.multiply(new BigDecimal("100"))
                                                    .remainder(new BigDecimal("10"));
            
            if (secondDecimalDigit.equals(BigDecimal.ZERO)) {
                // 第二位是0,舍去第三位的5,保留两位小数
                processedPrice = unitPrice.setScale(2, RoundingMode.DOWN);
            } else {
                // 第二位非0,保留三位小数
                processedPrice = scaledTo3;
            }
        } else {
            // 其他情况按银行家舍入(四舍六入五成双)处理到两位小数,若原函数用其他规则可替换
            processedPrice = unitPrice.setScale(2, RoundingMode.HALF_EVEN);
        }
        
        // 初始化格式化器
        DecimalFormatSymbols symbols = new DecimalFormatSymbols(localization);
        DecimalFormat df = new DecimalFormat("#,##0.00", symbols);
        String formatted = df.format(processedPrice);
        
        // 处理末尾无效零:去掉小数部分末尾连续的0,若小数全为0则去掉小数点
        formatted = formatted.replaceAll("\\.0+$", "");
        formatted = formatted.replaceAll("(\\.\\d*?)0+$", "$1");
        
        return formatted;
    }
}

测试验证

  • 输入new BigDecimal("2.1450000000000000000000000000000") → 输出"2.145"
  • 输入new BigDecimal("271.4050000000000000000000000000000") → 输出"271.40"

内容的提问来源于stack exchange,提问作者hagi10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:05:00