precision() 返回 BigDecimal 的有效数字总位数,需先 stripTrailingZeros() 归一化再调用,才能满足审计对“业务有效位数”的校验要求。
直接调用 precision() 并不能直接满足审计校验中对“有效位数”的语义要求,因为它的返回值是 bigdecimal 内部未调整值(unscaled value)的十进制位数,不是业务意义上“保留几位有效数字”的精度控制结果。审计校验关注的是数值表达的严谨性与可追溯性,比如“12.00”要体现 4 位有效数字、“0.0035”要体现 2 位有效数字——这需要结合 striptrailingzeros() 和 precision() 协同判断。
理解 precision() 的真实含义
precision() 返回的是该 BigDecimal 的**有效数字总位数(不含符号,含前导非零位和中间零)**,定义为 unscaledValue 的十进制位数。关键点:
- 对
new BigDecimal("123.45")→ unscaledValue = 12345,precision = 5 - 对
new BigDecimal("0.00600")→ stripTrailingZeros 后为6E-3,unscaledValue = 6,precision = 1(注意:末尾零已被剥离) - 对
new BigDecimal("0.00")→ stripTrailingZeros 后为0,precision = 1(规范规定零值 precision 恒为 1) - 它不反映小数点后保留了几位,也不等价于“显示位数”或“测量精度”
审计场景下获取业务有效位数的正确步骤
审计常需验证输入/输出是否符合预设有效数字规则(如“金额最多 6 位有效数字”),此时应:
- 先调用
stripTrailingZeros()消除冗余末尾零,使数值归一化 - 再调用
precision()获取归一化后的有效数字总位数 - 对负数,取绝对值后再 strip + precision(precision 本身已忽略符号)
- 特别处理零值:若原始值为 0 或经 strip 后为 0,按审计约定明确其有效位数(常见为 1,但部分标准要求按上下文补位)
实用校验代码示例
以下方法可嵌入审计工具类,用于断言某 BigDecimal 是否满足最大 N 位有效数字:
public static boolean hasValidPrecision(BigDecimal bd, int maxPrecision) {
if (bd == null) return false;
BigDecimal normalized = bd.stripTrailingZeros();
return normalized.precision() <= maxPrecision;
}
// 示例用法:
assert hasValidPrecision(new BigDecimal("120.00"), 3); // true(strip 后为 120,precision=3)
assert hasValidPrecision(new BigDecimal("0.00450"), 2); // true(strip 后为 4.5E-3,precision=2)
assert hasValidPrecision(new BigDecimal("100.000"), 3); // true(strip 后为 1E2,precision=1)
配合 scale 实现双重校验
仅靠 precision 不足以覆盖全部审计需求。例如,“汇率保留 8 位小数”是 scale 约束;“报价保留 5 位有效数字”才是 precision 约束。建议组合使用:
- 检查 scale:适用于限定小数点后固定位数的字段(如利率、汇率)
- 检查 precision:适用于科学计数、测量值、动态范围数值(如浓度、误差值)
- 审计日志中同时记录
toString()、precision()和scale(),便于回溯原始表示意图

















