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

Унарный оператор "~" - что именно происходит здесь?

Недавно я провел курс Java (1-недельный курс крушения), и мы рассмотрели некоторую двоичную математику.

Этот унарный оператор (тильда, который, как мне кажется, он называл?), был нам объяснен таким образом:

Он инвертирует битовую диаграмму, превращая все "0" в "1" и каждый "1" в "0". например В байт имеется 8 бит. Если у вас есть следующий байт: 00000000, инвертированное значение изменится на 11111111.

Вышеприведенное объяснение является ясным и кратким, и оно имеет для меня смысл. До тех пор, пока я не попытаюсь его реализовать.

Учитывая это:

byte x = 3;
byte y = 5;
System.out.println(~x);
System.out.println(~y);

Вывод:

-4  
-6

Я очень смущен тем, как это происходит.

Если +3 в бинарнике равно 11, то инверсия этого будет 00, что явно не -3.

Но поскольку в байте 8 бит, тогда не должно быть записано двоичное представление +3 как 00000011?

Что бы инвертироваться, чтобы стать 11111100. Преобразуется обратно в десятичное значение, это будет 252. Если, однако, вы пишете +3 как 011, тогда он действительно преобразуется в 100, что равно +4, но тогда как вы знаете это отрицательное число?

Как насчет того, попробуйте ли вы 0011, который преобразует в 1100, который, если вы используете первый бит в качестве знака, тогда он действительно становится -4.

А - так в этот момент я думал, что я куда-то ухожу.

Но тогда я добрался до второго значения y = 5.

Как мы это пишем? Используя ту же логику, +5 преобразуется в двоичный 0101, который инвертирует до 1010.

И теперь, когда я ужасно смущен. Это выглядит как знаковое значение -2 или значение без знака +10 десятичных чисел? Ни один из них не является -6, я распечатываюсь.

Опять же, если я увеличиваю длину до 8 цифр байта, +5 - 00000101, перевернутый - 11111010. И я действительно не могу найти способ превратить это в -6.

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

Google, похоже, не придумал что-нибудь по этому поводу - возможно, ему не нравится смотреть на маленькие указатели оператора.: - (

4b9b3361

Ответ 1

Из википедии: в двухзначной нотации неотрицательное число представлено его обычным двоичным представлением; в этом случае самый старший бит равен 0. Две операции дополнения - операция отрицания, поэтому отрицательные числа представлены двумя дополнениями абсолютного значения. Чтобы получить два дополнения двоичного числа, биты инвертируются или "переворачиваются", используя операцию побитового NOT; значение 1 добавляется к результирующему значению, игнорируя переполнение, которое происходит при взятии двух дополнений 0. http://en.wikipedia.org/wiki/Two%27s_complement

Итак, если у вас есть 0101, то есть +5, то инверсия равна 1010, которая равна -5.

Вы действительно не читаете 010 как 5, хотя, но когда вы видите 1 в начале, вы знаете, что, чтобы получить номер, вы должны снова инвертировать остальные цифры, чтобы получить положительное число, которое вы хочу отрицать. Если это имеет смысл.

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

Значение 8 десятичных знаков записывается как 01010, что отрицает значение 10101. Первая цифра (1) означает, что она отрицательная, а затем вы отбрасываете остальную часть назад, чтобы получить числовое значение: 1010.

Одна вещь, которую следует помнить, состоит в том, что два дополнения не совпадают с обычным подсчетом старой двоичной системы. В нормальном двоичном коде значение 10101 (что в двух дополнениях равно -8, как указано выше), конечно, 21. Я предполагаю, что здесь возникает путаница - как вы говорите разницу, глядя на них? Вы должны знать, какое представление использовалось для того, чтобы решить, каково значение этого числа на самом деле. Существует также одно дополнение, которое немного отличается.

Здесь дается хороший учебник по бинарной математике, включая одно и два дополнения. http://www.math.grin.edu/~rebelsky/Courses/152/97F/Readings/student-binary

Ответ 2

Смотрите эту демонстрацию: -

3 ->  0011
~3 -> 1100  -> -4 (2 complement)

5 -> 0101
~5 -> 1010 -> -6 (2 complement)

Так как целые числа со знаком сохраняются как 2 дополнения, то взятие 2 complement of 1100 дает вам 4. Теперь, поскольку 1100 - отрицательное число. Итак, результат -4. То же самое происходит с 1010.

1100 
0011  - 1 complement
0100  - 2 complement  - value = 4 (take negative)

Ответ 3

Подписанные целые числа почти повсеместно сохраняются с помощью двухкомпонентных дополнений. Это означает инвертирование битов (взятие одного дополнения) и добавление одного. Таким образом, у вас нет двух представлений целочисленного нуля (+0 и -0), а некоторые подписанные операции становятся проще реализовать в оборудовании.

Ответ 4

Java использует подписанные числа в Два дополнения. Ваши рассуждения будут правильными на C или других языках при использовании типов как "unsigned int" или "unsigned char".