Integer.valueOrabi c число работает нормально, но Float.valueOf того же числа дает NumberFormatException - PullRequest
5 голосов
/ 03 февраля 2020

Использование арабского c число Integer.valueOf("۱") возвращает целое число 1, но Float.valueOf("۱") или Float.parseFloat("۱") создает NumberFormatException, в то время как исключение не выдает никаких исключений, если вы используете Engli sh число Float.valueOf("1"). ошибка в java или есть какое-то объяснение?

Как мне разобрать такое число?

Я работаю в среде android;

Ответы [ 3 ]

4 голосов
/ 03 февраля 2020

Похоже, что Float.parseFloat() не поддерживает номера c в Восточной Арабской Республике. В качестве альтернативы вы можете использовать NumberFormat класс:

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
3 голосов
/ 03 февраля 2020

Ответ

В Float.valueOf("۱") нет проверки для разных языков или символов, проверяются только цифры 0-9. Integer.valueOf использует Character.di git () , чтобы получить значение каждого di git в строке.

Исследование / Объяснение

Я отладил оператор Float.valueOf("۱") с помощью отладчика Intellij. Если вы погрузитесь в FloatingDecimal. java, похоже, этот код определяет, какой символ следует считать как di git:

  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) для получения значения di git 1.

См. Character.di git ()

2 голосов
/ 03 февраля 2020

Спецификация Float.valueOf(String) гласит:

Начальные и конечные пробельные символы в s игнорируются. Пробелы удаляются как бы методом String.trim (); то есть, пробел ASCII и управляющие символы удаляются. Остальные s должны составлять FloatValue, как описано в лексических синтаксических правилах:

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

Наиболее близким лексическим правилом, которое у вас есть, является SignedInteger, которое состоит из необязательный знак, а затем 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) обратитесь к Integer.parseInt(String), который просто говорит:

Все символы в строке должны быть десятичными цифрами, за исключением того, что первый символ может быть знаком минус ASCII

"Десятичные цифры" шире, чем 0-9; можно использовать все, что в DECIMAL_DIGIT_NUMBER, например, "१२३" (бессовестный штекер).

Точнее,.


Так, это ведет себя как указано; считаете ли вы, что это правильная спецификация, это другой вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...