在Java中以本地敏感的方式验证十进制数

7

可能是重复问题:
安全且支持本地化的解析数字

我该如何以本地化方式验证包含小数的字符串?NumberFormat.parse允许过多,而Double.parseDouble仅适用于英语环境。以下是我的尝试:

public static void main(String[] args) throws ParseException {
    Locale.setDefault(Locale.GERMAN);

    NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.getDefault());
    Number parsed = numberFormat.parse("4,5.6dfhf");
    System.out.println("parsed = " + parsed); // prints 4.5 instead of throwing ParseException

    double v = Double.parseDouble("3,3"); // throws NumberFormatException, although correct
}

如果您的语言环境是德语,而输入为“3.3”而不是“3,3”,那么它应该抛出异常吗? - jlordo
解析数字 = numberFormat.parse("4.5.6dfhf"); 也可以工作并产生456... 呃... - assylias
jlordo:至少它应该接受正确的数字... - WannaKnow
assylias:是的,这就是我所说的它允许太多的意思... :( - WannaKnow
2个回答

2

In regards of the

Number parsed = numberFormat.parse("4,5.6dfhf");

如果遇到问题,可以使用NumberFormat.parse(String source, ParsePosition pos)方法,并检查解析停止的位置是否确实是字符串的最后一个位置。

此外,在第4.5.6个问题上,您可以尝试通过setGroupingUsed(boolean newValue)将分组设置关闭,因为我认为这是由于“.”字符是地区分组字符引起的问题。

应该像这样:

NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.getDefault());
numberFormat.setGroupingUsed(false);
ParsePosition pos;
String nString = "4,5.6dfhf";

Number parsed = numberFormat.parse(nString, pos);
if (pos.getIndex() == nString.length()) // pos is set AFTER the last parsed position
   System.out.println("parsed = " + parsed);
else
   // Wrong

1
但是这仍然会接受像“4.5.6”这样的无意义输入。 - Andreas Dolk
实际上,if(nString.length() == pos.getIndex())条件(不需要从长度中减去1)似乎是正确的条件。 - WannaKnow
Andreas_D:我猜点号就像英语环境下逗号一样被忽略了。 - WannaKnow
如果您觉得我的答案有用,那么将其标记为正确的会很棒!=) - Manuel Miranda
Manuel Miranda:我想两个答案都是正确的,但无论如何这似乎更通用,所以我会接受这个 :) - WannaKnow
显示剩余2条评论

1

根据您上面的评论,您可以使用:

String input = "3,3"; // or whatever you want
boolean isValid = input.matches("^\\d+([.,]\\d+)?$");
double value = Double.parseDouble(input.replaceAll(",", "."));

如果分隔符可以是逗号以外的其他字符,只需将其添加到方括号中:

double value = Double.parseDouble(input.replaceAll("[,]", "."));

问题在于不能保证该区域设置为德语。它可能是任何语言。您认为这对于任何区域设置都适用吗? - WannaKnow
只要分隔符是点或逗号,它就可以工作。我不知道有哪个地区的分隔符是其他东西。 - jlordo
空格怎么办?在某些语言环境中,“1 000 000”可能是有效的。试图重新开发一个依赖于语言环境的解析器听起来像是一场危险的游戏... - assylias
这取决于你想要多么严格。如果 1 000 000 是有效的,那么 1 00 0000 或者超过一个空格呢? - jlordo
@jlordo 没错 - 它涉及许多边界情况,而且很难做到完美。 - assylias
在我看来,输入中的数字只能是一串数字,后面可选跟随一个分隔符和另一组数字。而展示(漂亮打印)数字则是完全不同的事情。 - jlordo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接