Что значит сдвинуть число на один двоичный разряд влево
Как работают побитовые операции в JavaScript
Операции с битами не очень распространены в JavaScript, но бывает, что без них не обойтись
Чтобы понять, как работают побитовые операции в JS, тебе нужны 2 вещи:
Обзор всех побитовых операций в JavaScript
Примеры и использование
Побитовые операторы в JavaScript будет сложно понять, если применять их к десятичным числам.
Советую взять лист бумаги, карандаш и начать с того, чтобы перевести все десятичные числа из примеров в их двоичное представление.
Операторы И, ИЛИ, XOR
Давай попробуем их применить. Двоичное представление чисел записано справа в комментариях:
Будет проще считать, если ты запишешь двоичные числа в столбик. Вот так:
Сейчас, мы добавим console.log и проверим, правильно ли мы посчитали:
Важная особенность XOR в том, что, если ты с обеих сторон оператора напишешь одно и то же число, то в итоге всегда получишь ноль.
Оператор НЕ
работает иначе. Он называется унарным оператором и применяется к одному числу.
Если ты применишь оператор
дважды к одному и тому же числу, то ты вернешься туда, откуда начал:
Операторы побитового сдвига
Операторам побитового сдвига нужно 2 числа. Первое — само число, биты которого мы будем двигать. Второе — количество двоичных разрядов на которое будет выполнен сдвиг.
Сдвиг влево
Сдвинуть двоичное число на 1 разряд влево — это то же самое, что умножить его на два. Исключение — большие числа, которые после умножения не поместятся в памяти.
Сдвиг вправо
Правый сдвиг, в отличие от левого, делает числа меньше. Если число достаточно большое, то это будет эквивалентно делению на два. В нашем случае, с маленькими числами, все не так просто:
Не ленись, бери карандаш и проверь расчеты самостоятельно!
Беззнаковый сдвиг вправо
Беззнаковый сдвиг вправо отличается тем, что он не сохраняет знаковый бит (самый левый). Когда он применяется к отрицательным числам, то они станут положительными, потому что все пустые места будет заполнены нулями.
Не удивительно, что мы сдвинули 100 на 2 бита вправо и получили число в 4 раза меньше.
Выводы
Если ты занимаешься веб разработкой, то тебе, скорее всего, нечасто придется сталкиваться с побитовыми операциями в JavaScript.
С другой стороны, если ты ищешь работу и ходишь по собеседованиям, то это одна из любимых тем “на засыпку”. Многие задачи решаются очень красиво с помощью побитовых операций. Например, определить является ли число четным.
IT1300: Императивное программирование
В C# имеется возможность сдвигать двоичные разряды, составляющие целое значение, влево или вправо на заданную величину. Для этой цели в C# определены два приведенных ниже оператора сдвига двоичных разрядов.
Ниже приведена общая форма для этих операторов:
При сдвиге влево все двоичные разряды в указываемом значении сдвигаются на одну позицию влево, а младший разряд сбрасывается в нуль. При сдвиге вправо все двоичные разряды в указываемом значении сдвигаются на одну позицию вправо. Если вправо сдвигается целое значение без знака, то старший разряд сбрасывается в нуль. А если вправо сдвигается целое значение со знаком, то разряд знака сохраняется. Напомним, что для представления отрицательных чисел старший разряд целого числа устанавливается в 1. Так, если сдвигаемое значение является отрицательным, то при каждом сдвиге вправо старший разряд числа устанавливается в 1. А если сдвигаемое значение является положительным, то при каждом сдвиге вправо старший разряд числа сбрасывается в нуль.
При сдвиге влево и вправо крайние двоичные разряды теряются. Восстановить потерянные при сдвиге двоичные разряды нельзя, поскольку сдвиг в данном случае не является циклическим.
Ниже приведен пример программы, наглядно демонстрирующий действие сдвига влево и вправо. В данном примере сначала задается первоначальное целое значение, равное 1. Это означает, что младший разряд этого значения установлен. Затем это целое значение сдвигается восемь раз подряд влево. После каждого сдвига выводятся восемь младших двоичных разрядов данного значения. Далее процесс повторяется, но на этот раз 1 устанавливается на позиции восьмого разряда, а по существу, задается целое значение 128, которое затем сдвигается восемь раз подряд вправо.
Результат выполнения этой программы выглядит следующим образом.
Двоичные разряды соответствуют форме представления чисел в степени 2, и поэтому операторы сдвига могут быть использованы для умножения или деления целых значений на 2. Так, при сдвиге вправо целое значение удваивается, а при сдвиге влево — уменьшается наполовину. Разумеется, все это справедливо лишь в том случае, если крайние разряды не теряются при сдвиге в ту или иную сторону. Ниже приведен соответствующий пример.
Ниже приведен результат выполнения этой программы.
О битовых операциях
Авторизуйтесь
О битовых операциях
В этой статье я расскажу вам о том, как работают битовые операции. С первого взгляда они могут показаться вам чем-то сложным и бесполезным, но на самом деле это совсем не так. В этом я и попытаюсь вас убедить.
Введение
Побитовые операторы проводят операции непосредственно на битах числа, поэтому числа в примерах будут в двоичной системе счисления.
Я расскажу о следующих побитовых операторах:
Битовые операции изучаются в дискретной математике, а также лежат в основе цифровой техники, так как на них основана логика работы логических вентилей — базовых элементов цифровых схем. В дискретной математике, как и в цифровой технике, для описания их работы используются таблицы истинности. Таблицы истинности, как мне кажется, значительно облегчают понимание битовых операций, поэтому я приведу их в этой статье. Их, тем не менее, почти не используют в объяснениях побитовых операторов высокоуровневых языков программирования.
О битовых операторах вам также необходимо знать:
Побитовое ИЛИ (OR)
Побитовое ИЛИ действует эквивалентно логическому ИЛИ, но примененному к каждой паре битов двоичного числа. Двоичный разряд результата равен 0 только тогда, когда оба соответствующих бита в равны 0. Во всех других случаях двоичный результат равен 1. То есть, если у нас есть следующая таблица истинности:
38 | 53 будет таким:
A | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
B | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 |
A | B | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 |
Побитовое И (AND)
Побитовое И — это что-то вроде операции, противоположной побитовому ИЛИ. Двоичный разряд результата равен 1 только тогда, когда оба соответствующих бита операндов равны 1. Другими словами, можно сказать, двоичные разряды получившегося числа — это результат умножения соответствующих битов операнда: 1х1 = 1, 1х0 = 0. Побитовому И соответствует следующая таблица истинности:
Пример работы побитового И на выражении 38 & 53:
A | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
B | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 |
A & B | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
Исключающее ИЛИ (XOR)
Разница между исключающим ИЛИ и побитовым ИЛИ в том, что для получения 1 только один бит в паре может быть 1:
Например, выражение 138^43 будет равно…
A | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
B | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 |
A ^ B | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
С помощью ^ можно поменять значения двух переменных (имеющих одинаковый тип данных) без использования временной переменной.
Также с помощью исключающего ИЛИ можно зашифровать текст. Для этого нужно лишь итерировать через все символы, и ^ их с символом-ключом. Для более сложного шифра можно использовать строку символов:
Исключающее ИЛИ не самый надежный способ шифровки, но его можно сделать частью шифровального алгоритма.
Побитовое отрицание (NOT)
Побитовое отрицание инвертирует все биты операнда. То есть, то что было 1 станет 0, и наоборот.
Вот, например, операция
Результатом будет 20310
При использовании побитового отрицания знак результата всегда будет противоположен знаку исходного числа (при работе со знаковыми числами). Почему так происходит, узнаете прямо сейчас.
Дополнительный код
Здесь мне стоит рассказать вам немного о способе представления отрицательных целых чисел в ЭВМ, а именно о дополнительном коде (two’s complement). Не вдаваясь в подробности, он нужен для облегчения арифметики двоичных чисел.
Главное, что вам нужно знать о числах, записанных в дополнительном коде — это то, что старший разряд является знаковым. Если он равен 0, то число положительное и совпадает с представлением этого числа в прямом коде, а если 1 — то оно отрицательное. То есть, 10111101 — отрицательное число, а 01000011 — положительное.
Чтобы преобразовать отрицательное число в дополнительный код, нужно инвертировать все биты числа (то есть, по сути, использовать побитовое отрицание) и добавить к результату 1.
Например, если мы имеем 109:
A | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
A+1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
Побитовый сдвиг влево
Побитовые сдвиги немного отличаются от рассмотренных ранее битовых операций. Побитовый сдвиг влево сдвигает биты своего операнда на N количество битов влево, начиная с младшего бита. Пустые места после сдвига заполняются нулями. Происходит это так:
Побитовый сдвиг вправо
Как вы могли догадаться, >> сдвигает биты операнда на обозначенное количество битов вправо.
Если операнд положительный, то пустые места заполняются нулями. Если же изначально мы работаем с отрицательным числом, то все пустые места слева заполняются единицами. Это делается для сохранения знака в соответствии с дополнительным кодом, объясненным ранее.
Вывод
Итак, теперь вы знаете больше о битовых операциях и не боитесь их. Могу предположить, что вы не будете использовать >>1 при каждом делении на 2. Тем не менее, битовые операции неплохо иметь в своем арсенале, и теперь вы сможете воспользоваться ими в случае надобности или же ответить на каверзный вопрос на собеседовании.
Привет! Сегодня исследуем интересное 5 задание из ЕГЭ по информатике нового формата 2021.
Пятое задание ЕГЭ по информатике в основном связано с алгоритмами и автоматами.
Задача (классическая, Алгоритм):
На вход алгоритма подаётся натуральное число N. Алгоритм строит по нему новое число R следующим образом.
1. Строится двоичная запись числа N.
2. К этой записи дописываются справа ещё два разряда по следующему правилу:
а) складываются все цифры двоичной записи, и остаток от деления суммы на 2 дописывается в конец числа (справа). Например, запись 10000 преобразуется в запись 100001;
б) над этой записью производятся те же действия — справа дописывается остаток от деления суммы цифр на 2.
Полученная таким образом запись (в ней на два разряда больше, чем в записи исходного числа N) является двоичной записью искомого числа R.
Укажите такое наименьшее число N, для которого результат работы алгоритма больше 97. В ответе это число запишите в десятичной системе счисления.
У нас на вход поступает натуральное (обычное, не дробное, положительное) число N.
Рассмотрим первое правило формирование выходного числа. На выходе получается двоичная запись числа N. Нарисуем схематично первое правило формирования выходного числа.
Рассмотрим теперь второе правило формирования числа. Сказано, что дописываются два разряда справа к тому двоичному числу, которое получили в первом пункте.
Про первый дополнительный разряд написано в пункте a второго правила: «складываются все цифры двоичной записи, и остаток от деления суммы на 2 дописывается в конец числа (справа). Например, запись 10000 преобразуется в запись 100001».
Если сказать более просто, то автомат подсчитывает количество единиц у первоначального двоичного числа N, полученного в первом пункте. Если количество чётное, то автомат в первый дополнительный разряд должен поставить 0. Если количество нечётное, то автомат в первый дополнительный разряд должен поставить 1.
Про второй дополнительный разряд сказано в пункте б второго правила. Автомат сделает тоже самое, что и в предыдущем пункте, только теперь подсчёт единиц будет происходить не только в двоичной записи числа N, но и в первом дополнительном разряде.
В вопросе просят указать входящее наименьшее число N, чтобы автомат выдал число R больше 97.
Т.к. число R должно быть больше 97, то переведём число 98 (97 + 1) в двоичный вид, чтобы можно было оценить входящее число N.
Получилось число 1100010. Будем рассматривать (начиная с 1100010) числа на выполнение правил, которые заданы для автомата. Если все правила будут выполнены, значит, мы получили то число, по которому вычислим изначальное N. Нам нужно получить именно минимальное число, поэтому мы и начали с минимального возможного претендента для числа R (98).
Видим, что подходит число 1100110. В части числа, которая является двоичным представлением N, количество единиц равно 3. Число 3 нечётное, значит, в первом дополнительном разряде должна стоять 1 (единица).
Проверим второй дополнительный разряд. Теперь считаем единицы не только в двоичном представлении числа N, но так же и в первом дополнительном разряде! Количество единиц равно 4. Число 4 чётное. Значит, во втором дополнительном разряде должен стоять 0 (ноль). Все правила работы автомата выполняются в числе 1100110.
Чтобы найти искомое число N, отбросим два дополнительных разряда от найденного 1100110.
Правило: Если от двоичного числа отбросить младший разряд, то оно разделится на 2 целочисленным образом (т.е. делим на 2, если есть остаток, убираем его).
Значит двоичное представление искомого числа N равно 11001, а десятичное 25.
Изучим ещё одну классическую задачу задания 5 из ЕГЭ по информатике.
Задача (классическая, Автомат)
Автомат получает на вход пятизначное число. По этому числу строится новое число по следующим правилам.
1. Складываются отдельно первая, третья и пятая цифры, а также вторая и четвёртая цифры.
2. Полученные два числа записываются друг за другом в порядке неубывания без разделителей.
Пример. Исходное число: 63 179. Суммы: 6 + 1 + 9 = 16; 3 + 7 = 10. Результат: 1016.
Укажите наименьшее число, при обработке которого автомат выдаёт результат 723.
В подобных задачах из ЕГЭ по информатике нумерация происходит начиная со старшего разряда.
Составим краткую запись для первого правила:
Второе правило заключается в том, что мы «соединяем» два числа, полученных в первом пункте, причём, сначала идёт меньшее число, а затем большее.
Рассмотрим число 723.
Разбить на числа 72 и 3 нельзя, т.к. вначале пишется меньшее число. Значит, разбиваем на 7 и 23.
Нам нужно указать наименьшее пятизначное входящее число, поэтому стремимся более старшие разряды сделать как можно меньше! Пусть самый старший разряд (1 разряд) равен 1 (минимальное значение для старшего разряда). Тогда нужно с помощью суммы 3-его и 5-ого разряда набрать 22. Но это не возможно, т.к. максимум с двух разрядов получается 9+9=18. Поэтому приходим к выводу, что самое маленькое значение для 1-ого разряда будет 23-18=5, а третий и пятый разряд будут по 9.
Получаем окончательный результат 50979.
Следующая задача иногда встречается в тренировочных вариантах ЕГЭ по информатике.
Задача (Кузнечик)
Исполнитель КУЗНЕЧИК живёт на числовой оси. Начальное положение КУЗНЕЧИКА – точка 0. Система команд Кузнечика:
Вперед 7 – Кузнечик прыгает вперёд на 7 единиц,
Назад 5 – Кузнечик прыгает назад на 5 единиц.
Какое наименьшее количество раз должна встретиться в программе команда «Назад 5», чтобы Кузнечик оказался в точке 19?
В данной задаче у нас есть числовая ось на которой живёт кузнечик.
Кузнечик может прыгать либо на 7 шагов вперёд, либо на 5 шагов назад. На другое количество шагов Кузнечик прыгать не может!
Если бы Кузнечик начинал не с нулевой отметки, мы бы прибавили начальную координату к левой части уравнения.
Вспомним таблицу умножения:
Задача из ЕГЭ по информатике на побитовый сдвиг:
Задача(редкая, сдвиг влево)
У исполнителя, который работает с положительными однобайтовыми двоичными числами, две команды, которым присвоены номера:
1. сдвинь влево
2. вычти 1
Выполняя первую из них, исполнитель сдвигает число на один двоичный разряд влево, причём на место освободившегося бита ставится 0. Выполняя вторую команду исполнитель вычитает из числа 1. Исполнитель начал вычисления с числа 91 и выполнил цепочку команд 112112. Запишите результат в десятичной системе.
Здесь есть всего две команды у исполнителя: сдвинуть биты влево и вычесть 1.
Правило: Если к двоичному числу приписать справа ноль, то это число увеличится в два раза.
В нашей задаче число однобайтовое, значит число не превышает 255. Если при умножении на 2, получаем число большее, чем 255, то мы должны взять остаток от деления на 256
осталось проделать цепочку команд 112112.
Если была бы команда сдвиг вправо, то тогда у числа просто убирался бы правый бит (т.е. происходило бы целочисленное деление на 2)
В задании 5 ЕГЭ по информатике может встретится задача на исполнителя чертёжника.
Задача (Исполнитель Чертежник)
Исполнитель Чертежник имеет перо, которое можно поднимать, опускать и перемещать. При перемещении опущенного пера за ним остается след в виде прямой линии. У исполнителя существуют следующие команды:
Сместиться на вектор (а, Ь) – исполнитель перемещается в точку, в которую можно попасть из данной, пройдя а единиц по горизонтали и b – по вертикали.
Запись: Повторить 5[ Команда 1 Команда 2] означает, что последовательность команд в квадратных скобках повторяется 5 раз.
Чертежник находится в начале координат. Чертежнику дан для исполнения следующий алгоритм:
Сместиться на вектор (5,2)
Сместиться на вектор (-3, 3)
Повторить 3[Сместиться на вектор (1,0)]
Сместиться на вектор (3, 1)
На каком расстоянии от начала координат будет находиться исполнитель Чертежник в результате выполнения данного алгоритма?
После первой команды Сместиться на вектор (5,2) Исполнитель чертёжник окажется:
После второй команды Сместиться на вектор (-3, 3)
Следующая команда Повторить 3[Сместиться на вектор (1,0)]
Следующая команда Сместиться на вектор (3, 1)
Расстояние от начала координат находит по теореме Пифагора:
Значит, расстояние равно 10.
Последняя задача довольно часто печатается в тренировочных заданиях по ЕГЭ по информатике.
Задача (Исполнитель)
У исполнителя УТРОИТЕЛЬ две команды, которым присвоены номера:
1. вычти 1
2. умножь на 3
Первая из них уменьшает число на экране на 1, вторая – увеличивает его в три раза.
Запишите порядок команд в программе получения из числа 3 числа 16, содержащей не более 5 команд, указывая лишь номера команд.
(Например, программа 21211 это программа
умножь на 3
вычти 1
умножь на 3
вычти 1
вычти 1
которая преобразует число 1 в 4.)
У нас есть две команды: вычитание 1 и умножить число на 3. Другие действия мы производить не можем!