Значение я для (i == -i && я!= 0) для возврата true в Java

У меня есть следующее условие if.

if (i == -i && i != 0)

Какое значение i вернет true для этого условия в Java?

Я не могу думать о каком-либо таком значении i, рассматривая двухкомпонентную в Java.

Я также хотел бы иметь алгебраическое доказательство того, что ответ на это условие имеет (в контексте с Java)?

Ответ 1

Единственное значение int, для которого оно работает, - Integer.MIN_VALUE.

Это потому, что целые числа отрицаются с помощью двух дополнительных способов.

Использование

System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));

вы видите, что Integer.MIN_VALUE есть

10000000000000000000000000000000

Взятие отрицательного значения производится путем первой замены 0 и 1, которая дает

01111111111111111111111111111111

и добавив 1, что дает

10000000000000000000000000000000

Как вы можете видеть в ссылке, которую я дал, Wikipedia упоминает проблему с наибольшими отрицательными числами и указывает это единственное исключение:

Самое отрицательное число в двух дополнениях иногда называют "странное число", потому что это единственное исключение.

Конечно, у вас есть такое же явление для Long.Min_Value, если вы сохраните его в переменной long.

Обратите внимание, что это происходит только из-за выбора, который был сделан в отношении двоичного хранения int в Java. Другое (плохое) решение могло бы, например, состоять в том, чтобы свести на нет, просто изменив самый старший бит и не изменив остальные биты, это позволило бы избежать этой проблемы с MIN_VALUE, но сделало бы 2 разных значения 0 и сложную двоичную арифметику (как вы бы увеличили, например?).

Ответ 2

Значение, которое вы ищете, Integer.MIN_VALUE.


Я также хотел бы иметь алгебраическое доказательство того, что ответ имеет это условие (в контексте с java)?

Это не по теме для Stack Exchange. Но вы можете сделать это, начиная с определения целых чисел Java (JLS 4.2)

"Интегральные типы - это байты, короткие, int и long, значениями которых являются 8-битные, 16-битные, 32-битные и 64-битные подписанные два символа-дополнения..."

и

"Значения интегральных типов являются целыми числами в следующих диапазонах...     Для int, от -2147483648 до 2147483647, включительно"

и определение оператора Unary '-' Java (JLS 15.15.4):

"Для целых значений отрицание является таким же, как и вычитание из нуля. Язык программирования Java использует представление двух дополнений для целых чисел, а диапазон значений двух дополнений не является симметричным, поэтому отрицание максимального отрицательного int или long приводит к тому же максимальному отрицательному числу. В этом случае происходит переполнение, но исключение не генерируется. Для всех целых значений x, -x равно (~ x) +1."

Ответ 3

В дополнение к ответам, данным до сих пор...

Всего четыре значения

int i = Integer.MIN_VALUE;
long i = Long.MIN_VALUE;
Integer i = Integer.valueOf(Integer.MIN_VALUE);
Long i = Long.valueOf(Long.MIN_VALUE);

Обернутые значения распаковываются, поэтому они также верны для этого выражения.

Примечание. Документы Math.abs.

public static int abs (int a)

Возвращает абсолютное значение int стоимость. Если аргумент не отрицателен, аргумент возвращается. Если аргумент отрицательный, возвращается отрицание аргумента.

Обратите внимание, что если аргумент равен значению Integer.MIN_VALUE, самая отрицательная представляемая значение int, результатом является то же самое значение, которое отрицательно.

и

public static long abs (long a)

Возвращает абсолютное значение длинного значения. Если аргумент не отрицательный, аргумент возвращается. Если аргумент отрицательный, отрицание аргумента возвращается.

Обратите внимание, что если аргумент равен значению Long.MIN_VALUE, наиболее отрицательное представимое длинное значение, результатом является то же значение, который является отрицательным.

Удивительно, что Math.abs может вернуть отрицательное число. Это происходит либо потому, что: а) нет положительных значений для -MIN_VALUE в этих случаях; б) выполнение результатов расчета - при переполнении.

Интересно также, почему не Byte.MIN_VALUE, Short.MIN_VALUE этого не делают. Это связано с тем, что - изменяет тип на int для них и, следовательно, не переполняется.

Character.MIN_VALUE не имеет проблемы, так как он равен 0.

Float.MIN_VALUE и Double.MIN_VALUE имеют другое значение. Это наименьшее представимое значение, большее нуля. Таким образом, они имеют действительные отрицательные значения, которые сами по себе не являются.

Ответ 4

Как упоминалось выше, это выполняется только Integer.MIN_VALUE. Что касается доказательства, позвольте мне предложить более легкое для понимания объяснение, отличное от двоичного (хотя оно все еще связано с этим).

Обратите внимание, что Integer.MIN_VALUE равно -2^31 или -2147483648, а Integer.MAX_VALUE равно 2^31-1 или 2147483647. -Integer.MIN_VALUE 2^31, который теперь слишком велик для целого (поскольку он прошел MAX_VALUE), что вызывает переполнение целых чисел, что делает его Integer.MIN_VALUE снова. Это единственный Integer, который делает это, поскольку MIN_VALUE является единственным числом без отрицательного эквивалента, кроме 0.

Ответ 5

Ориентировочное алгебраическое доказательство, используя modulo 2^32 арифметику:

i == -i можно переписать как 2 * i == 0 (добавление i с обеих сторон) или i << 1 == 0.

Это уравнение имеет два решения вида i == 0 >> 1, а именно 0b и 10000000000000000000000000000000b, полученные сдвигом либо в 0, либо 1 слева.

Решение i == 0 исключается, остается решение i == 100000000000000000000000000000000b.

Ответ 6

Возможно, он не слишком образован, но вместо того, чтобы думать, что вы можете запустить этот код:

    for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
    {
        if (i == -i && i != 0)
        {
            System.out.println(i);
        }
    }

чтобы увидеть, что он печатает

-2147483648
-2147483648

бесконечно:)