不幸的是 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 ......这种处理本地化,但需要做更多的工作来支持小数的“,”......