Вопрос

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

верно.

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

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

Это было полезно?

Решение

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

<цитата>

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

Другие советы

Целочисленное хранилище переполняется и не указывается любым способом, как указано в 3-м издании JSL. :

<цитата>

Встроенные целочисленные операторы никоим образом не указывают на переполнение или потерю значимости. Целочисленные операторы могут выдавать сгенерированный код кода кода при распаковке преобразования (§5.1. 8) пустая ссылка обязательна. Помимо этого, единственные целочисленные операторы, которые могут вызывать исключение, (§11) - оператор целочисленного деления NullPointerException (§15.17.2) и оператор целочисленного остатка / (§15.17.3) , которые генерируют код %, если правый операнд равен нулю, и операторы увеличения и уменьшения ArithmeticException ( §15.15.1 , §15.15.2 ) и ++ ( §15. 14.3 , §15.14.2 ), который может выдавать сгенерированный код кода метки при конвертации упаковки (§ 5.1.7) , а памяти недостаточно для выполнения преобразования.

Пример в 4-битном хранилище:

родовое слово

MAX_INT + 1:

родовое слово

Вы должны понимать, как целые значения представлены в двоичной форме и как работает двоичное сложение. 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

<цитата>

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

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

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

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

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

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

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

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

Cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483647, -2147483646, -2147483645, ... and so forth to the far most right again and on and on, its nature of summing machine on this bit depth.

Some examples:

int a = 2147483647;

System.out.println(a);

gives: 2147483647

System.out.println(a+1);

gives: -2147483648 (cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483648, -2147483647, -2147483646, ... and so fores to the far most right again and on and on, its nature of summing machine on this bit depth)

System.out.println(2-a); 

gives:-2147483645 (-2147483647+2 seems mathematical logical)

System.out.println(-2-a);

gives: 2147483647 (-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 some loop described in previous answers)

System.out.println(2*a);

gives: -2 (2147483647+2147483647 -> -2147483648+2147483646 again mathematical logical)

System.out.println(4*a);

gives: -4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647 -> -2-2 (according to last answer) -> -4)`

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top