Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Как работает оператор ~ инверсии в java?

#java #битовые_операции


Есть код:

   for(int i = -2; i<2; i++)
    System.out.printf("Инверсия %d даст %d. \n", i, ~i );


На выходе:

Инверсия -2 даст 1. 
Инверсия -1 даст 0. 
Инверсия 0 даст -1. 
Инверсия 1 даст -2.


Оператор инверсии похоже реализован так:

Operator ~ (int i){
return -i-1;
}


Но пишут, что инверсия инвертирует нули в единицы. Хорошо, для -2 (инт для упрощения
4 бита берём) 1010, первый бит - знак минус. Значит инверсия будет 0101, то есть 5.
 Дополнительный код: 0101 + 1 = 0110 - итого 6. Короче, никак у меня в теории не удаётся
инвертировать код 

Вопрос: Как на самом деле (объясните на единицах и нулях) работает этот проклятый
оператор? И зачем разработчики языка сделали его работу именно такой?
    


Ответы

Ответ 1



Инверсия является побитовой операцией и преобразует хранящиеся в памяти единицы в нули и нули в единицы. Чтобы понять почему она так работает с типом int нужно изучит структуру представления примитивного типа int в памяти. Примитивный тип int состоит из четырех байт. Старший бит старшего байта отвечает за знак числа, остальные - за значение. Отрицательные числа хранятся в дополнительном коде. Разберем пример для числа -2: System.out.println(Integer.toBinaryString(-2)); //11111111 11111111 11111111 11111110 - битовое представление числа -2 после операции побитовой инверсии мы получим: 00000000 00000000 00000000 00000001, что эквивалентно десятичной 1 Таким образом для корректного использования побитовых операций важно знать внутреннюю структуру обрабатываемых данных и при необходимости работать только с нужной частью битов используя маски и сдвиги. Необходимо учитывать и то, что другие целочисленные типы при многих операциях так же приводятся к типу int.

Ответ 2



Отрицательные числа компьютер хранит в дополнительном коде. С точки зрения математики, дополнительный код - это кольцо вычетов по модулю 2N. Не пугайтесь, это страшное слово означает всего лишь, что к отрицательным числам добавляется 2N, где N - число разрядов. К примеру, 32х-битное число -1 в памяти хранится как 232-1 = 4294967295. Или, в двоичном виде, 11111111 11111111 11111111 111111112. Аналогично, число -2 в памяти хранится как 232-2 = 11111111 11111111 11111111 111111102, а число -3 - как 232-3 = 11111111 11111111 11111111 111111012. Легко видеть, что инверсия одного бита с точки зрения математики - это вычитание его из 1: 1-1=0, а 1-0=1. Инверсия же всех 32х бит числа - это вычитание их его из 32х единиц. Но, как уже было показано выше, число состоящее из 32х единиц - это -1. Таким образом, математически вы правы, оператор инверсии действительно работает так как вы написали: ~x = -1-x Но не следует думать что эта формула - его реализация. Это всего лишь его математическое свойство, а реализован он по определению - как инверсия всех бит числа. Кстати, если перенести единицу в другую часть, получится более интересная формула: ~x + 1 = -x Интересна эта формула тем, что является реализацией оператора "унарный минус" в процессоре. Именно так процессоры вычитают целые числа: x - y = x + ~y + 1

Комментариев нет:

Отправить комментарий