> For the complete documentation index, see [llms.txt](https://opu.gitbook.io/101/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://opu.gitbook.io/101/prakticheskie-raboty/prakticheskaya-rabota-1.-rabota-s-bitami.md).

# Практическая работа 1. Работа с битами

**Бит** (**bit**) - мельчайшая единица информации. 1 бит информации - символ или сигнал, который может принимать два значения: включено или выключено, да или нет. В двоичной системе это 1 или 0.

Байт представляет собой последовательность из 8 бит, каждый из которых может принимать значение 0 или 1, независимо от других бит в последовательности.

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIRpqQqMB9pGF_EHwpO%2F-MIRt_7kt3rXVi7t_sb0%2Fimage.png?alt=media\&token=3da508d4-cd83-445c-8e9c-cbb94d02fc7f)

### Перевод из двоичной в десятичный формат и обратно

Для перевода в двоичную систему и обратно существуют специальные формулы, но удобно использовать следующий подход - для перевода числа удобно разложить число на сумму слагаемых, который представляют два в определенной степени. Например:

$$
65 = 2^6 + 2^0 = 64 + 1
$$

Каждый бит последовательности справа налево представляет слагаемое 2 в степени от `0` до `n-1`, где `n` - количество бит в последовательности. Таким образом, 65 можно представить в двоичном формате следующим образом

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIRpqQqMB9pGF_EHwpO%2F-MIRv4SZJoaBJB6UAr2h%2Fimage.png?alt=media\&token=39f280e3-4a33-495e-a545-20a71c5b4d46)

Те же вычисления можно провести в обратном порядке. Допустим, есть число в двоичном формате

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIRvjsjpiABjtuz6Lcv%2F-MIRw8SFbq9bJwx8EUG9%2Fimage.png?alt=media\&token=102338d1-3a8f-4fda-a1cc-800114639e7e)

Переведем его в десятичный формат

$$
2^6 +2^5 + 2^3 + 2^1 = 64 + 32 + 8 + 2 = 106
$$

### Представление отрицательных чисел. Прямой и дополнительный код

Самый очевидный вариант для представления отрицательного числа - отвести один бит для обозначения - положительное ли число или отрицательное. Если бит равен `0` - число положительное, если бит равен `1` - число отрицательное.

Нам удобнее отвести под бит знака крайне левый бит в последовательности, чтобы он не мешал выполнять арифметические действия с битовыми последовательностями. В таком случае, в одном байте максимально положительным числом будет 127 или `2**8 - 1`

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIRwWYAhEurf9XNy9pK%2F-MIRy2Rq5fYZ07EDyGl6%2Fimage.png?alt=media\&token=c388639c-f94c-4b23-b8d1-fe6db06c52e5)

Такое представление называется **прямым кодом**.

Прямой код - это представление числа в двоичной системе счисления, при котором первый (старший) разряд отводится под знак числа. Если число положительное, то в левый разряд записывается 0, если число отрицательное, то в левый разряд записывается 1.

Количество значений, которое можно поместить в 7-разрядной ячейке со знаком в дополнительном разряде равно 256. Это совпадает с количеством значений, которое можно поместить в 8-разрядную ячейку без указания знака. Однако диапазон значений уже другой, ему принадлежат значения от -128 до 127 включительно.

В вычислительной технике прямой код используется почти исключительно для представления положительных чисел.

Для отрицательных чисел используется так называемый **дополнительный код**. Это связано с удобством выполнения операций над числами в компьютере.

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

Все остальные разряды числа в дополнительном коде сначала инвертируются, то есть заменяются противоположными (0 меняется на 1, 1 меняется на 0). Далее следует прибавить единицу к получившемуся числу. Например, число 54 выглядит следующим образом

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIRwWYAhEurf9XNy9pK%2F-MIS02zN7XUBLB1mwPTy%2Fimage.png?alt=media\&token=7e769258-ae63-4393-8c9a-99bdb041d16b)

Для того, чтобы получить `-54`, инвертируем биты и прибавим 1

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIRwWYAhEurf9XNy9pK%2F-MIS18uKAdhgw9L-MEYT%2Fimage.png?alt=media\&token=4e9ebd49-b6eb-49fb-b066-45086a946b7d)

### Побитовые операции (bitwise operations)

Операция **AND** (побитовое И). Обозначается в Python как `&`. Если оба операнда равны 1, результирующий разряд равен 1, если хотя бы один бит из пары равен 0, то результат тоже будет 0.

Операция **OR** (побитовое ИЛИ). Обозначается в Python как `|`. Если оба операнда равны 0, результирующий разряд равен 0, если хотя бы один бит из пары равен 1, то результат тоже будет 1.

Операция **XOR** (исключающее ИЛИ), сложение по модулю 2. Обозначается в Python как `^`. Если оба операнда равны 1 или оба равны 0, результирующий разряд равен 0, если хотя бы один бит из пары равен 1, то результат тоже будет 1.

|  x  |  y  | x \| y | x & y | x ^ y |
| :-: | :-: | :----: | :---: | :---: |
|  0  |  0  |    0   |   0   |   0   |
|  0  |  1  |    1   |   0   |   1   |
|  1  |  0  |    1   |   0   |   1   |
|  1  |  1  |    1   |   1   |   0   |

Операция **NOT**, побитовое отрицание (или побитовое НЕ, дополнение). Обозначается в Python как `~` и является унарной. Заменяет бит на противоположный.

|  x  | \~x |
| :-: | :-: |
|  0  |  1  |
|  1  |  0  |

#### Битовые сдвиги

К битовым операциям также относят битовые сдвиги. При сдвиге значения биты копируются в соседние по направлению сдвига. Различают несколько видов сдвигов - логический, арифметический и циклический, в зависимости от обработки крайних битов.

При логическом сдвиге значение последнего бита по направлению сдвига теряется, а первый приобретает нулевое значение.

Арифметический сдвиг аналогичен логическому, но число считается знаковым, представленным в дополнительном коде. Так, при правом сдвиге старший бит сохраняет свое значение. Левый арифметический сдвиг идентичен логическому.

При циклическом сдвиге, значение последнего бита по направлению сдвига копируется в первый бит.&#x20;

Приведем пример логического сдвига. Допустим у нас есть следующее число

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIS7TvQ2nmTmLX8IzA3%2F-MIS8dmTQ0IosKwiru-D%2Fimage.png?alt=media\&token=a7a06122-9eea-4481-8928-1296eb9b6744)

Реализуем сдвиг влево на 2 позиции. В Python эта операция будет обозначаться как `<< 2`. В результате получим следующую последовательность битов

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIS7TvQ2nmTmLX8IzA3%2F-MIS9ZH159xvhOg3heDF%2Fimage.png?alt=media\&token=ce015755-8f8f-4de9-b898-81a45ace2430)

Реализуем сдвиг вправо на 3 позиции. В Python эта операция будет обозначаться как `>> 3`. В результате получим следующую последовательность битов

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MIS7TvQ2nmTmLX8IzA3%2F-MISA4zAMndI7KMAPYKM%2Fimage.png?alt=media\&token=59cff281-8b27-4b90-89eb-acae7e696706)

### Представление вещественных чисел

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

Число с плавающей запятой состоит из набора отдельных двоичных разрядов, условно разделенных на так называемые **знак** (англ. sign), **порядок** (англ. exponent) и **мантиссу** (англ. mantis). В наиболее распространённом формате (стандарт IEEE 754) число с плавающей запятой представляется в виде набора битов, часть из которых кодирует собой мантиссу числа, другая часть — показатель степени, и ещё один бит используется для указания знака числа (0 — если число положительное, 1 — если число отрицательное).

Во многих языках существуют встроенные типы для чисел одинарной точности и двойной точности (например, типы `float` и `double` в языках C или Java). В Python тип `float` изначально является вещественным числом с двойной точностью.

Число одинарной точности - компьютерный формат представления чисел, занимающий в памяти одно машинное слово (в случае 32-битного компьютера — 32 бита или 4 байта).

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MISAV7zwg7w_CNH6ncS%2F-MISC-C-pTSw6bYYj-0K%2Fimage.png?alt=media\&token=1c010333-ffda-4dea-9e6e-f8be5d9f8e59)

Число двойной точности - компьютерный формат представления чисел, занимающий в памяти два машинных слова (в случае 32-битного компьютера — 64 бита или 8 байт).

![](https://3745156914-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnmXmI-D1suCZkVT17D%2F-MISAV7zwg7w_CNH6ncS%2F-MISC5fAREboEX6fczo0%2Fimage.png?alt=media\&token=c155e34c-24ad-4989-8179-f3a1981d3cd2)
