Integer.valueOf 阿拉伯数字工作正常但 Float.valueOf 相同的数字给出 NumberFormatException

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

使用阿拉伯数字 Integer.valueOf("۱") returns 整数 1 但 Float.valueOf("۱")Float.parseFloat("۱") 抛出 NumberFormatException 而如果你使用英文则不会抛出任何异常数字 Float.valueOf("1"),它是 java 中的错误还是有一些解释?

如何解析这样的数字?

我在 android 环境中工作;

Float.valueOf(String) 的规范说:

Leading and trailing whitespace characters in s are ignored. Whitespace is removed as if by the String.trim() method; that is, both ASCII space and control characters are removed. The rest of s should constitute a FloatValue as described by the lexical syntax rules:

FloatValue:
  Signopt NaN
  Signopt Infinity
  Signopt FloatingPointLiteral
  Signopt HexFloatingPointLiteral
  SignedInteger
...

最接近你所拥有的词法规则是SignedInteger, which consists of an optional sign, and then Digits,它只能是0-9

Digits:
  Digit
  Digit [DigitsAndUnderscores] Digit

Digit:
  0
  NonZeroDigit

NonZeroDigit:
  (one of)
  1 2 3 4 5 6 7 8 9

另一方面,Integer.valueOf(String) refer to Integer.parseInt(String),它简单地说:

The characters in the string must all be decimal digits, except that the first character may be an ASCII minus sign

"Decimal digits" 比 0-9 宽;什么都在DECIMAL_DIGIT_NUMBER can be used, for example (不要脸的外挂)。

更准确地说,.


所以,这符合规定;您是否认为这是正确的规范是另一回事。

好像是Float.parseFloat() does not support Eastern-Arabic numbers. Alternatively, you can use NumberFormatclass:

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);

输出:

1.5

回答

Float.valueOf("۱")中没有检查不同的语言或字符,它只检查数字0-9Integer.valueOf 使用 Character.digit() 获取字符串中每个数字的值。

Research/Explanation

我用 Intellij 调试器调试了语句 Float.valueOf("۱")。如果你深入研究 FloatingDecimal.java,就会发现这段代码决定了哪个字符应该被算作一个数字:

  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++;
        }

正如你所看到的,没有检查不同的语言,它只检查数字 0-9.

单步执行 Integer.valueOf 时,

public static int parseInt(String s, int radix)

s = "۱"radix = 10 一起执行。

然后parseInt方法调用Character.digit('۱',10)得到1的数字值。

Character.digit()