不幸的是,Double.parseDouble(s)或new BigDecimal(s)似乎是您最好的选择。
你提到了本地化问题,但不幸的是,没有一种方法可以在没有用户指定的情况下可靠地支持所有语言环境。这是不可能的。
有时,您可以根据逗号或句点先使用哪个来推断方案,如果两者都使用,则可能无法推断,那么为什么要尝试呢?最好拥有您知道在某些情况下可靠工作的系统,而不是依赖可能在更多情况下工作但也可能产生错误结果的系统......
数字“123,456”代表什么?123456还是123.456?
只需根据用户指定的语言环境删除逗号、空格或句点。默认删除空格和逗号。如果要使其更严格,只删除逗号或空格,而不是两者都删除,并且仅在有句点的情况下才在句点前删除。实际上,手动检查它们是否按三个间隔可以很容易地完成。事实上,自定义解析器可能在这里最容易。
这是一个概念验证。虽然有点(非常)混乱,但我认为它有效,而且您可以理解其中的思路 :)。
public class StrictNumberParser {
public double parse(String numberString) throws NumberFormatException {
numberString = numberString.trim();
char[] numberChars = numberString.toCharArray();
Character separator = null;
int separatorCount = 0;
boolean noMoreSeparators = false;
for (int index = 1; index < numberChars.length; index++) {
char character = numberChars[index];
if (noMoreSeparators || separatorCount < 3) {
if (character == '.') {
if (separator != null) {
throw new NumberFormatException();
} else {
noMoreSeparators = true;
}
} else if (separator == null && (character == ',' || character == ' ')) {
if (noMoreSeparators) {
throw new NumberFormatException();
}
separator = new Character(character);
separatorCount = -1;
} else if (!Character.isDigit(character)) {
throw new NumberFormatException();
}
separatorCount++;
} else {
if (character == '.') {
noMoreSeparators = true;
} else if (separator == null) {
if (Character.isDigit(character)) {
noMoreSeparators = true;
} else if (character == ',' || character == ' ') {
separator = new Character(character);
} else {
throw new NumberFormatException();
}
} else if (!separator.equals(character)) {
throw new NumberFormatException();
}
separatorCount = 0;
}
}
if (separator != null) {
if (!noMoreSeparators && separatorCount != 3) {
throw new NumberFormatException();
}
numberString = numberString.replaceAll(separator.toString(), "");
}
return Double.parseDouble(numberString);
}
public void testParse(String testString) {
try {
System.out.println("result: " + parse(testString));
} catch (NumberFormatException e) {
System.out.println("Couldn't parse number!");
}
}
public static void main(String[] args) {
StrictNumberParser p = new StrictNumberParser();
p.testParse("123 45.6");
p.testParse("123 4567.8");
p.testParse("123 4567");
p.testParse("12 45");
p.testParse("123 456 45");
p.testParse("345.562,346");
p.testParse("123 456,789");
p.testParse("123,456,789");
p.testParse("123 456 789.52");
p.testParse("23,456,789");
p.testParse("3,456,789");
p.testParse("123 456.12");
p.testParse("1234567.8");
}
}
编辑:显然,这需要扩展以识别科学计数法,但这应该很简单,特别是因为你不必在e之后实际验证任何内容,如果它格式不正确,你只需让parseDouble失败即可。
此外,将NumberFormat适当地扩展也可能是一个好主意。有一个getSeparator()用于解析数字和一个setSeparator用于提供所需的输出格式... 这样可以处理本地化,但要支持','作为小数点还需要做更多的工作...
NumberFormat
,然而我明确指出这在这里不起作用的原因。 - Michael McGowan