#java #c
#java #c
Вопрос:
Целочисленные переменные состоят из 4 байт или 32 бит, а 2 ^ 31 и -2^ 31 в двоичных числах равны 32 битам. Но когда вы помещаете 2 ^ 31 = 2,147,483,648 в целочисленную переменную, она показывает ошибку, но для -2 ^ 31 это нормально. Почему?
Комментарии:
1. Потому что вам нужно где-то поместить 0
2. Да, положительный диапазон начинается с 0
3. Подсказка: об этом легче рассуждать с помощью небольших чисел. 8 бит могут хранить от -128 до 127 включительно, в общей сложности 256 значений.
4. Еще один совет: самый значимый (старший) бит — это знаковый бит (в дополнительном обозначении 2). Когда это значение установлено, число становится отрицательным.
Ответ №1:
Целочисленные переменные состоят из 4 байт или 32 бит, а 2 ^ 31 и -2^31 в двоичных числах равны 32 битам
Нет, это не так.
в базовом двоичном коде отрицательные числа не являются чем-то особенным. У нас есть нули и единицы. Там нет знака «нет».
В двоичном 2^31
формате становится:
1000 0000 0000 0000 0000 0000 0000 0000
В двоичном формате -2 ^ 31 не может быть представлено без предварительного определения способа хранения отрицательных чисел.
Обычно (и java делает это тоже) используется система, называемая дополнением 2. дополнение 2 звучит очень сложно: возьмите число, скажем, 5. Представьте его в двоичном формате (для этого упражнения давайте использовать байт, то есть 8 бит): 0000 0101
. Теперь переверните все биты: 1111 1010
, а затем добавьте 1: 1111 1011
.
То есть -5 в двоичном дополнении signed 2.
Эта причудливая система обладает двумя удивительными свойствами: математика продолжает работать в обычном режиме, не требуя знать, подписано число или нет. Давайте попробуем. -5 2 — это -3, верно? давайте посмотрим.. что 1111 1011
такое 0000 0010
? Я получаю, не беспокоясь о дополнении 2 вообще 1111 1101
. Давайте применим преобразование дополнения 2: сначала переверните биты: 0000 0010
, затем добавьте 1: 0000 0011
, что равно … 3. Так -5 2
что -3. Проверьте. Другим удивительным свойством является то, что он не «тратит» 2 2^32
«слота» на нули. Давайте попробуем дополнить 2 0: 0000 0000
, затем перевернем все биты: 1111 1111
, затем добавим 1: 0000 0000
(с битовым переполнением, которое мы игнорируем). Это хорошо: 0 — это его собственное дополнение 2. Мы не можем отличить 0 от -0, но в целом это хорошо.
Другим свойством этой системы является то, что первый бит является битом ‘sign’. если оно равно 1, оно отрицательное, если 0, это не так.
Давайте попробуем дополнить 2 1000 0000 0000 0000 0000 0000 0000 0000
. Сначала переверните биты: 0111 1111 1111 1111 1111 1111 1111 1111
. Затем добавьте 1: 1000 0000 0000 0000 0000 0000 0000 0000
. Подожди. Это… что у нас было!!
Да. и поскольку первый бит отрицательный, 1000 0000 0000 0000 0000 0000 0000 0000
ОТРИЦАТЕЛЬНЫЙ.
Возможно, вы забываете, что 0 — это вещь, а 0 не является ни положительным, ни отрицательным.
Итак, если 0 должно быть представимым и получает знаковый бит 0 (ноль в битах равен 0000000 … конечно), это означает, что «пробел» в половине всех представимых чисел, начинающихся с 0, теперь на единицу меньше, потому что 0 съел один слот. Это означает, что существует еще одно отрицательное число, которое можно представить против положительные числа. (или, альтернативно, что 0 «считается» положительным, поэтому 0 — это первое положительное число, а -1 — первое отрицательное число). Следовательно, должно быть по крайней мере 1 отрицательное число, которое не имеет положительного эквивалента в дополнении 2. Это число равно… 2 ^ 31. -2^31
подходит для 32-битной подписи. 2^31
не делает этого.
Давайте представим себе 3-разрядное число со знаком и дополнением 2. Мы можем перечислить их все:
000 = 0
001 = 1
010 = 2
011 = 3
100 = -4
101 = -3
110 = -2
111 = -1
Обратите внимание, что там -4, а 4 нет, и обратите внимание, как мы рассмотрели 8 чисел. 2^3 = 8
— 3 бита могут представлять 8 чисел, не более того.
Ответ №2:
Из документации oracle мы получили это:
int: По умолчанию тип данных int представляет собой 32-разрядное целое число со знаком, дополняющее два, которое имеет минимальное значение -2 ^ 31 и максимальное значение 2 ^ 31-1. В Java SE 8 и более поздних версиях вы можете использовать тип данных int для представления 32-разрядного целого числа без знака, которое имеет минимальное значение 0 и максимальное значение 2 ^ 32-1. Используйте класс Integer для использования типа данных int в качестве целого числа без знака. См. Раздел Классы чисел для получения дополнительной информации. Статические методы, такие как compareUnsigned, divideUnsigned и т.д., были добавлены в класс Integer для поддержки арифметических операций с целыми числами без знака.
Из другого документа (простого и вполне понятного) мы получили:
Когда целое число подписывается, один из его битов становится знаковым битом, что означает, что максимальная величина числа уменьшается вдвое. (Таким образом, 32-разрядный int без знака может хранить до 2 ^ 32-1, тогда как его подписанный аналог имеет максимальное положительное значение 2 ^ 31-1.)
В Java все целочисленные типы подписаны (кроме char).
Это потому, что первый бит указывает знаковый бит. Максимальное положительное значение, которое он может сохранить 2^31 - 1
. Для этого доступно много ресурсов.