能否通过DecimalFormat实现解析时校验字符串的精确两位小数位数?
如何用DecimalFormat实现严格校验两位小数的解析函数
首先得明确:DecimalFormat的默认解析行为是宽松的,它不会主动拒绝小数位数不足的输入,而是会自动补零到指定的最小小数位数——这就是你当前代码无法生效的原因,比如"1.1"会被它默默解析成1.10,不会抛出任何异常。
要实现"必须精确两位小数"的校验,你需要在DecimalFormat解析之外,额外添加字符串格式的校验。下面提供两种可靠的方案:
方案一:正则校验前置 + DecimalFormat解析
先用正则表达式严格匹配"整数部分(可选负号)+ 小数点 + 两位小数"的格式,通过校验后再用DecimalFormat解析,这样能从源头过滤不符合要求的输入。
示例代码:
import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParseException; import java.util.regex.Pattern; public class StrictDecimalParser { // 正则匹配:可选负号,至少一位整数,小数点,两位小数 private static final Pattern TWO_DECIMAL_PATTERN = Pattern.compile("^-?\\d+\\.\\d{2}$"); private static DecimalFormat getDecimalFormat() { DecimalFormatSymbols symbols = new DecimalFormatSymbols(); symbols.setDecimalSeparator('.'); DecimalFormat df = new DecimalFormat("#0.00", symbols); df.setParseBigDecimal(true); return df; } public static BigDecimal parseStrictTwoDecimals(String input) throws ParseException { // 先校验格式 if (!TWO_DECIMAL_PATTERN.matcher(input).matches()) { throw new ParseException("输入必须是精确两位小数的数字格式", 0); } // 再解析 return (BigDecimal) getDecimalFormat().parse(input); } }
测试用例:
parseStrictTwoDecimals("1.10")→ 返回1.10(正常)parseStrictTwoDecimals("1.1")→ 抛出ParseException(符合预期)parseStrictTwoDecimals("-123.45")→ 返回-123.45(支持负数)parseStrictTwoDecimals("123")→ 抛出ParseException(无小数点,不符合)
方案二:ParsePosition校验 + 小数位数检查
如果你不想用正则,也可以借助ParsePosition跟踪解析进度,确保整个字符串都被解析,同时手动检查输入字符串的小数位数是否为2位:
import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParseException; import java.text.ParsePosition; public class StrictDecimalParser { private static DecimalFormat getDecimalFormat() { DecimalFormatSymbols symbols = new DecimalFormatSymbols(); symbols.setDecimalSeparator('.'); DecimalFormat df = new DecimalFormat("#0.00", symbols); df.setParseBigDecimal(true); return df; } public static BigDecimal parseStrictTwoDecimals(String input) throws ParseException { DecimalFormat df = getDecimalFormat(); ParsePosition pos = new ParsePosition(0); BigDecimal result = (BigDecimal) df.parse(input, pos); // 检查是否整个字符串都被解析(避免"1.10abc"这种无效输入) if (pos.getIndex() != input.length()) { throw new ParseException("输入包含无效字符", pos.getIndex()); } // 检查小数位数是否精确为2位 int decimalPointIndex = input.indexOf('.'); if (decimalPointIndex == -1 || input.length() - decimalPointIndex - 1 != 2) { throw new ParseException("输入必须精确包含两位小数", decimalPointIndex == -1 ? input.length() : decimalPointIndex + 1); } return result; } }
为什么原代码不生效?
你设置的setMinimumFractionDigits(2)只是告诉DecimalFormat:解析后的值至少要有两位小数,如果输入的小数位数不足,它会自动补零,而不是拒绝输入。比如"1.1"会被解析为1.10,但这不符合你"必须输入两位小数"的校验需求。
内容的提问来源于stack exchange,提问作者Gilberto T.
相关产品推荐
相关产品推荐

