简体   繁体   中英

NL locale returns ambiguous number

if I want to use different number formats across Europe to one format (double), it doesn't seem to work.

Locale locale = new Locale("nl", "NL");
NumberFormat nf= NumberFormat.getNumberInstance(locale);
returns nf.parse("4,000.00").doubleValue();

it returns 4.000 instead of 4000.0, but when enter nf.parse("900,00") it works (returns 900.0) Another time I enter 4000 and it converts to 4000.0 (expected). So now I am left with inconsistent types. I want to convert each number to the same double format. can you guide me?

now I am left with inconsistent types

This is incorrect. The behaviour is entirely consistent and according to spec.

In dutch, the comma is the wholes/fractions separator: There can be only one, and everything to the left is the wholes, and to the right of it, the fractional part. The dot is the thousands separator.

900,00

This is parsed as nine hundred, whole. 900 is to the left of the comma - so those are the wholes. 00 is the fractional part, which is nothing, so, you end up with 900. As expected - a dutch person reading 900,00 would assume that said 'nine hundred'.

4000

Obviously, that's four thousand. No problems there.

4,000.00

That's 4,000 - ie four, with 000 as fractional part, and that is how this is parsed . The .00 isn't parsed at all.

Wait, what?

NumberFormat is designed to parse multiple numbers from a stream of text. Even the .parse(string) version of it. Here, try it:

Locale locale = new Locale("nl", "NL");
NumberFormat nf= NumberFormat.getNumberInstance(locale);
System.out.println(nf.parse("4,000hey now this is strange").doubleValue();

works and runs fine, and prints '4'.

Fixing it

If you really want to fix it, you have a few strategies. One of them, is to first verify that the entire input is valid (eg with a regular expression) and only then parsing it.

Another option is to explicitly check that the whole input is consumed. You can do that:

String input = "4,000.00";
ParsePosition ps = new ParsePosition(0);

Locale locale = new Locale("nl", "NL");
NumberFormat nf = NumberFormat.getNumberInstance(locale);
double v = nf.parse(input, ps).doubleValue();
if (ps.getIndex() != input.length()) throw new IllegalArgumentException("Not a number: " + input);

The above code parses 900,00 as nine hundred, parser 4000 as four thousand, same for 4.000 , and throws an exception if you attempt to toss 4,000.00 at it. Which is, indeed, not a valid anything in dutch locale.

I want something that parses both 4,000.00 as 4000, but also 900,00 as 900.

That is highly inconsistent and implies you want 4,000 to be parsed as 4 and yet 4,000.00 as 4000 . If you want this, you're on your own and have to write it from scratch, no built in library (or, as far as I know, any external one) would do such utter befuddled inconsistent craziness.

NB: Note that the snippet would parse 4.000.00 as 400000 and works fine; inconsistent application of thousands separators is leniently parsed by NumberFormat and you can't tell it to be strict. In fact, 4.1.23.4567 is parsed as 41234567 - the only reason 4,000.00 is not parsed in the first place is because dots are not allowed in the fractional part at all. If you don't want that, you're again stuck, you can't use NumberFormat then. Regexes maybe, but you're now on the hook for writing one for each locale you care to support.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM