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

Почему Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

истинно.

Я понимаю, что целое число в Java 32 бит и не может превышать 2 ^ 31-1, но я не понимаю, почему добавление 1 к его MAX_VALUE приводит к MIN_VALUE, а не к какому-либо исключению. Не упоминать что-то вроде прозрачного преобразования в более крупный тип, как это делает Ruby.

Является ли это поведение указанным где-то? Могу ли я на это положиться?

4b9b3361

Ответ 1

Потому что целое число переполняется. Когда он переполняется, следующее значение Integer.MIN_VALUE. Соответствующие JLS

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

Ответ 2

Целочисленное хранилище переполняется и которое никак не указано, как указано в JSL 3rd Ed.:

Встроенные целочисленные операторы никак не указывают на переполнение или недополнение. Операторы Integer могут вызывать NullPointerException, если требуется преобразование unboxing (§5.1.8) нулевой ссылки. Кроме того, единственными целыми операторами, которые могут вызывать исключение (§11), являются оператором деления целого числа / (§15.17.2) и целочисленный оператор остатка % (§15.17.3), которые бросают ArithmeticException, если правый операнд равен нулю, а операторы приращения и декремента ++ (§15.15.1, §15.15.2) и -- (§15.14.3, §15.14.2), который может вызывать OutOfMemoryError при преобразовании бокса (§5.1.7), и для выполнения преобразования недостаточно памяти.

Пример в 4-разрядном хранилище:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)

MAX_INT + 1:

 0111+
 0001
 ----
 1000

Ответ 4

Вы должны понимать, как целочисленные значения представлены в двоичной форме и как работает двоичное сложение. Java использует представление, называемое двумя дополнениями, в котором первый бит числа представляет собой его знак. Всякий раз, когда вы добавляете 1 к самому большому java Integer, который имеет битовый знак 0, тогда его битовый знак становится 1, а число становится отрицательным.

Эти ссылки объясняются с более подробной информацией: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

-

Спецификация языка Java рассматривает это поведение здесь: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

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

Это означает, что вы можете положиться на это поведение.

Ответ 5

По той же причине, почему дата меняется при пересечении международной линии дат: там есть разрыв. Он встроен в природу двоичного добавления.

Ответ 6

Это хорошо известная проблема, связанная с тем, что целые числа представлены как два дополнения вниз на двоичном уровне, Когда вы добавляете 1 к максимальному значению двух дополнительных номеров, вы получаете минимальное значение. Честно говоря, все целые числа вели себя таким образом до того, как существовал Java, и изменение этого поведения для языка Java добавило бы дополнительные накладные расходы для целочисленной математики и запутанных программистов, поступающих с других языков.

Ответ 7

Когда вы добавляете 3 (в двоичном формате 11) в 1 (в двоичном формате 1), вы должны изменить на 0 (в двоичном 0) все двоичные 1, начиная с правой, пока вы не получите 0, который вы должны изменить на 1. Integer.MAX_VALUE имеет все места, заполненные 1, поэтому остается только 0 s.

Ответ 8

В большинстве процессоров арифметические команды не имеют режима для отказа при переполнении. Они устанавливают флаг, который необходимо проверить. Это дополнительная инструкция, поэтому, вероятно, медленнее. Для того чтобы языковые реализации были как можно быстрее, языки часто указываются для игнорирования ошибки и продолжения. Для Java поведение указано в JLS. Для C язык не определяет поведение, но современные процессоры будут вести себя как Java.

Я считаю, что есть предложения для (неудобных) библиотек Java SE 8 для переполнения, а также для неподписанных операций. Поведение, которое я считаю популярным в мире DSP, - это зажать значения в максимумах, поэтому Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [not Java].

Я уверен, что будущие языки будут использовать произвольные прецизионные ints, но не на какое-то время. Требуется более дорогая компоновка компилятора для быстрого запуска.