Подтвердить что ты не робот

Преобразование 32-битной двоичной строки с Integer.parseInt не выполняется

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

Integer.parseInt("11000000000000000000000000000000",2);

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

В соответствии с docs максимальное значение Integer 2^31-1. Что в двоичном формате:

1111111111111111111111111111111

Иными словами, 31 1 в строке.

Ответ 3

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

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

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

Ответ 4

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

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

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

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

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

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

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