Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integer.valueOf Arabic number works fine but Float.valueOf the same number gives NumberFormatException

Using Arabic number Integer.valueOf("۱") returns integer 1 but Float.valueOf("۱") or Float.parseFloat("۱") throws NumberFormatException while it won't throw any exceptions if you use English number Float.valueOf("1"), is it a bug in java or there's some explanation?

How can I parse such a number?

I'm working in android environment;

like image 836
Alireza Jamali Avatar asked Dec 10 '22 01:12

Alireza Jamali


2 Answers

It seems that Float.parseFloat() does not support Eastern-Arabic numbers. Alternatively, you can use NumberFormat class:

Locale EASTERN_ARABIC_NUMBERS_LOCALE = new Locale.Builder()
                                                 .setLanguage("ar")
                                                 .setExtension('u', "nu-arab")
                                                 .build();
float f = NumberFormat.getInstance(EASTERN_ARABIC_NUMBERS_LOCALE)
                      .parse("۱٫۵")
                      .floatValue();
System.out.println(f);

OUTPUT:

1.5
like image 99
Eng.Fouad Avatar answered Dec 21 '22 23:12

Eng.Fouad


Answer

In Float.valueOf("۱") there is no check for different languages or character, it only checks the digits 0-9. Integer.valueOf uses Character.digit() to get the value of each digit in the string.

Research/Explanation

I debugged the statement Float.valueOf("۱") with Intellij debugger. If you dive into FloatingDecimal.java, it appears this code determines which character should be counted as a digit:

  digitLoop:
        while (i < len) {
            c = in.charAt(i);
            if (c >= '1' && c <= '9') {
                digits[nDigits++] = c;
                nTrailZero = 0;
            } else if (c == '0') {
                digits[nDigits++] = c;
                nTrailZero++;
            } else if (c == '.') {
                if (decSeen) {
                    // already saw one ., this is the 2nd.
                    throw new NumberFormatException("multiple points");
                }
                decPt = i;
                if (signSeen) {
                    decPt -= 1;
                }
                decSeen = true;
            } else {
                break digitLoop;
            }
            i++;
        }

As you can see, there is no check for different languages, it only checks the digits 0-9.

While stepping through Integer.valueOf execution,

public static int parseInt(String s, int radix)

executes with s = "۱" and radix = 10.

The parseInt method then calls Character.digit('۱',10) to get the digit value of 1.

See Character.digit()

like image 35
jackguinea Avatar answered Dec 21 '22 23:12

jackguinea