Как выглядит битовое представление чисел 1 и -1 в Java int
Что проверяют
Понимаете ли вы, что int в Java это 32 бита в дополнительном коде и что это зафиксировано спецификацией языка, а не зависит от платформы. Следом обычно просят объяснить, чему равно -1 >>> 1 или почему Math.abs(Integer.MIN_VALUE) возвращает отрицательное число.
Как отвечать
Хватит двух строк и одного правила:
- 1:
00000000 00000000 00000000 00000001, в шестнадцатеричном виде0x00000001; - -1:
11111111 11111111 11111111 11111111, то есть0xFFFFFFFF, выставлены все 32 бита; - правило: чтобы получить
-x, инвертируют все битыxи прибавляют единицу,-x == ~x + 1. Старший бит работает как знак: 0 у неотрицательных, 1 у отрицательных.
Зачем такой код: ноль в нём один, без +0 и -0, как в обратном коде, а сложение и вычитание выполняются той же схемой, что и для беззнаковых чисел. Отсюда несимметричный диапазон: от -2^31 до 2^31 - 1, и Math.abs(Integer.MIN_VALUE) возвращает сам MIN_VALUE, потому что положительной пары у него нет.
Показать можно прямо в коде: Integer.toBinaryString(-1) вернёт 32 единицы, а Integer.toBinaryString(1) просто "1", ведущие нули не печатаются.
Следствия, которые стоит назвать:
- сдвиги:
-1 >> 1остаётся-1, потому что арифметический сдвиг размножает знаковый бит, а-1 >>> 1даётInteger.MAX_VALUE; - приведение:
(byte) 255равно-1, и чтобы прочитать байт как беззнаковый, пишутb & 0xFF; - беззнаковые операции: беззнакового
intв языке нет, но с Java 8 естьInteger.toUnsignedString,Integer.compareUnsigned,Integer.divideUnsigned.
Где спотыкаются
Говорят, что -1 это единица с установленным старшим битом, 0x80000001. Так число выглядело бы в прямом коде, а в Java этот набор битов означает -2147483647.
Путают >> и >>> и не могут объяснить, почему сдвиг отрицательного числа не совпадает с делением: -5 >> 1 даёт -3, а -5 / 2 даёт -2, потому что деление округляет к нулю.
Смешивают представление числа и порядок байтов. Порядок важен только при сериализации: DataOutputStream и ByteBuffer по умолчанию пишут big-endian, а для little-endian формата его задают через order(ByteOrder.LITTLE_ENDIAN).