Преобразование 32-разрядной двоичной строки с помощью Integer.parseInt завершается неудачно - PullRequest
12 голосов
/ 17 января 2012

Почему эта часть кода не работает:

Integer.parseInt("11000000000000000000000000000000",2);

Exception in thread "main" java.lang.NumberFormatException: For input string: "11000000000000000000000000000000"

Насколько я понимаю, Integer - это 32-битное значение. Количество нулей и единиц в верхнем коде равно 32. Если их 31, код работает. Почему это так?

Ответы [ 4 ]

16 голосов
/ 17 января 2012

Ваш код завершается ошибкой, потому что он пытается проанализировать число, которое потребует 33 бита для сохранения в виде целого числа со знаком.

Знаковое int - это 32-битное значение в представлении дополнения до двух, где первый битбудет указывать знак числа, а оставшиеся 31 бит - значение числа.(-ish.) Java поддерживает только целые числа со знаком, и parseInt() и друзья не должны анализировать битовые комбинации двух дополнений - и, таким образом, интерпретировать 1 или (возможно подразумеваемый) 0 в 32-й позиции справакак знакОни предназначены для поддержки анализа удобочитаемой репрезентации, которая является необязательной - (или +) для знака, за которым следует абсолютное значение числа.

В этом контексте этоложная интуиция, которая приводит вас к ожидаемому поведению, которое вы описываете: если вы анализируете любую другую базу, кроме базы 2 (или, возможно, других обычно используемых степеней двух), вы ожидаете первую цифруввода, чтобы повлиять на знак?Очевидно, что вы не будете;скажем, parseInt("2147483648") return -2147483648 по проекту было бы PHP-уровнем сумасшествия.

В двухслойных базах специального корпуса тоже ощущается странность.Лучше иметь отдельный подход к обработке битовых комбинаций, например, тот, что в этот ответ .

4 голосов
/ 17 января 2012

В соответствии с документами максимальное значение целого числа равно 2^31-1. Который в двоичном виде:

1111111111111111111111111111111

Другими словами, 31 1 подряд.

2 голосов
/ 29 августа 2013

Это потому, что для Integer.parseInt «11000000000000000000000000000000» - это не двоичное представление дополнения -1073741824, а положительное значение, которое не вписывается в диапазон значений int от -2147483648 до 2147483647. Но мы можем проанализировать двоичное строковое представление дополнения двух с помощьюBigInteger:

int i = new BigInteger("11000000000000000000000000000000", 2).intValue()

это дает ожидаемый результат -1073741824

0 голосов
/ 17 января 2012

Даже если ваша строка «11 ..... много нулей» является допустимым двоичным представлением отрицательного целого числа, Integer.parseInt () завершается с ошибкой.Я считаю это ошибкой.

Добавление небольшого легкомыслия, так как при перечитывании этого поста это звучит слишком педантично, я понимаю, что Oracle, вероятно, не очень заботится, думаю ли я, что это ошибка или нет.: -)

Вы можете попробовать:

   long avoidOverflows = Long.parseLong("11000000000000000000000000000000",2);
   int thisShouldBeANegativeNumber = (int)avoidOverflows);
   System.out.println(avoidOverflows + " -> " + thisShouldBeANegativeNumber);

вы должны увидеть
3221225472 -> -1073741824

Иногда вам приходится делать это с цветами в зависимости от того, какони хранятся в виде текста.

Кстати, точная вещь может произойти, если вы анализируете шестнадцатеричное представление, и вы анализируете отрицательное число, такое как "88888888".Вам нужно использовать Long.parseLong (), а затем конвертировать.

...