0

Correct string representations of numbers depend on the Locale: "2.5" is a valid number in the US, but not in Germany. The German representation of this number is "2,5". Is there any way in Java to detect that a given string is a valid number with respect to a certain Locale?

var decimal = DecimalFormat.getInstance(Locale.Germany).parse("2.5");

The DecimalFormat just ignores the "." and reads the number as 25, which is not what I need. I need a way to tell that this is not a valid number representation in Germany. How can I get such a test?

The solutions proposed as answers to the question here either ignore the locale altogether, or propose a home-made parsing algorithm which does neither consider the complexities nor the multiple differences in the locales. Is there a library which does that job simple and complete?

Gregor
  • 2,737
  • 4
  • 26
  • 48
  • 1
    `.` is a thousands separator in Germany. So is `123.456` valid? That’s why the period is ignored. – Boris the Spider Dec 18 '21 at 11:19
  • 1
    [Does This help](https://stackoverflow.com/a/44480179/4725875)? – DevilsHnd Dec 18 '21 at 11:25
  • 1
    There is that annoying `DecimalFormat.parse(String text, ParsePosition pos)` API that you can use to check that parsing reached the end. It's mentioned in the end of the most popular answer in your link by the way. – Alexey Veleshko Dec 18 '21 at 12:32

2 Answers2

0

With the help of the comments, I figured, that indeed the GERMANY locale uses "." as a grouping separator. But still, according to me, "2.5" is not a valid decimal, as ".", if at all, is used as a by-thousand-grouping, but there is only one digit after the ".". This should be an error, but it isn't. Also the ParsePosition equals the length of the string, because the string is parsed without error until the end.

I would consider this as a bug in the DecimalFormat implementation, or, if not a bug, at least as an incomplete implementation.

On the other hand, as pointed out by @VGR above, the Scanner class does the job as expected.

Gregor
  • 2,737
  • 4
  • 26
  • 48
0

Scanner is not as lenient as NumberFormat:

Scanner scanner = new Scanner(s).useLocale(Locale.GERMANY);

if (!scanner.hasNextDouble()) {
    throw new ParseException(
        "Not a valid number: \"" + s + "\"", 0);
}

double decimal = scanner.nextDouble();
if (scanner.hasNext()) {
    throw new ParseException(
        "Extra characters found after value in \"" + s + "\"", 
        s.replace("^\\s*\\S+", "").length());
}
VGR
  • 37,458
  • 4
  • 42
  • 54
  • Yes, you are right: a Germany localised Scanner accepts "3.500" but not "3.5". That's exactly the behaviour I would have expected by the DecimalFormat too! – Gregor Dec 18 '21 at 17:50