Skip to content

Commit 9418080

Browse files
committed
feat(post): add js-bit post
1 parent 4198f42 commit 9418080

6 files changed

Lines changed: 211 additions & 0 deletions

File tree

content/posts/js-bit.md

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
---
2+
title: Битовые манипуляции в JavaScript
3+
tags:
4+
- note
5+
- javascript
6+
- web
7+
date: 2024-03-18
8+
exclusive: true
9+
keywords:
10+
- bit
11+
- manipulation
12+
references:
13+
- name: Using Bitwise operators in JavaScript
14+
url: https://www.digitalocean.com/community/tutorials/using-bitwise-operators-in-javascript
15+
- name: The Absolute Essentials for Bit Manipulation in JavaScript
16+
url: https://lucasfcosta.com/2018/12/25/bitwise-operations.html
17+
- name: Bit Twiddling Hacks
18+
url: https://graphics.stanford.edu/~seander/bithacks.html
19+
---
20+
21+
Вся информация на компьютерах хранится в двоичном формате. Буквы, цифры, массивы, хэшмапы, все.
22+
23+
Цифры в свою очередь эффективней хранить в двоичной системе счисления. Любое число в десятичной системе можно перевести в двоичную.
24+
25+
По сути все числа хранятся в таком формате:
26+
::ContentDiagram{src="/posts/js-bit/js-bit-1.svg"}
27+
::
28+
29+
Мы можем легко посмотреть репрезентацию десятичного числа в двоичной системе с помощью `toString`:
30+
```javascript
31+
10.tostring(2); // 1010
32+
4.toString(2); // 100
33+
2.toString(2); // 10
34+
1.toString(2); // 1
35+
```
36+
37+
Парсить данные числа в свою очередь удобно через `parseInt`:
38+
```javascript
39+
parseInt('1010', 2); // 10
40+
parseInt('100', 2); // 4
41+
parseInt('10', 2); // 2
42+
parseInt('1', 2); // 1
43+
```
44+
45+
Мы также можем записывать двоичные числа с помощью `0b`:
46+
```javascript
47+
console.log(0b1010); // 10
48+
console.log(0b100); // 4
49+
console.log(0b10); // 2
50+
console.log(0b1); // 1
51+
```
52+
53+
# Нормализация Значений
54+
%% TODO %%
55+
56+
# Логические Операторы
57+
Для битовых чисел есть специальные логические операторы. Цель их существования - манипуляция с битовыми значениями.
58+
## «Битовый И»: `&`
59+
Оператор `&` сравнивает каждый разряд двоичного числа и отдает `1` только в том случае, если разряды в двух числах являются единицей:
60+
61+
```javascript
62+
console.log(0b1001 & 0b0110) // 0000 => 0
63+
console.log(0b1000 & 0b1100) // 1000 => 8
64+
console.log(0b1111 & 0b1111) // 1111 => 1 + 2 + 4 + 8 => 15
65+
```
66+
67+
::ContentDiagram{src="/posts/js-bit/js-bit-2.svg"}
68+
::
69+
70+
## «Битовый ИЛИ»: `|`
71+
Оператор `|` сравнивает каждый разряд двоичного числа, если один из разрядов равен `1`, то данный оператор вернет `1`:
72+
```javascript
73+
console.log(0b1001 | 0b0110) // 1111 => 15
74+
console.log(0b1000 | 0b1100) // 1100 => 12
75+
console.log(0b1111 | 0b1111) // 1111 => 1 + 2 + 4 + 8 => 15
76+
```
77+
78+
::ContentDiagram{src="/posts/js-bit/js-bit-3.svg"}
79+
::
80+
81+
## «Битовый НЕ»: `~`
82+
Для того чтобы инверсировать все разряды в числе используется оператор `~`:
83+
84+
```javascript
85+
console.group("0b0 (0)")
86+
console.log(0b0); // 0
87+
console.log(~0b0); // -1 (0b111111...111)
88+
console.groupEnd();
89+
90+
console.group("0b1 (1)")
91+
console.log(0b1); // 1
92+
console.log(~0b1); // -2 (0b11111111...1110)
93+
console.groupEnd();
94+
95+
console.group("0b100 (4)")
96+
console.log(0b100); // 4
97+
console.log(~0b100); // -5 (0b11111...11011)
98+
console.groupEnd();
99+
```
100+
101+
Вот как происходит изменение битов:
102+
::ContentDiagram{src="/posts/js-bit/js-bit-4.svg"}
103+
::
104+
105+
По сути мы просто меняем каждую цифру из числа по логике («*там где был 0 - ставим 1, а там где была 1 - ставим 0*»)
106+
107+
Может возникнуть резонный вопрос: «**Почему при `~0` мы получаем `-1` (в десятичной), а не максимальное число (где все разряды - `1`)?**»
108+
109+
При инвертировании `00000000`, мы должны получить `11111111`, данное число мы и **получаем**. Все дело в том, как устроены отрицательные двоичные числа.
110+
111+
Вот хорошее видео на эту тему: [Binary: Plusses & Minuses (Why We Use Two's Complement) - Computerphile](https://www.youtube.com/watch?v=lKTsv6iVxV4)
112+
113+
## «Битовый Сдвиг влево»: `<<`
114+
Битовый сдвиг влево двигает все цифры двоичного числа влево и добавляет в конец 0. Справа от данного оператора можно указать сколько именно битов нам нужно сдвинуть.
115+
116+
```js
117+
console.log(0b101); // 5
118+
console.log(0b101 << 1); // 0b1010 -> 10
119+
120+
console.log(0b101); // 5
121+
console.log(0b101 << 2); // 0b10100 -> 20
122+
```
123+
124+
::ContentDiagram{src="/posts/js-bit/js-bit-5.svg"}
125+
::
126+
127+
## «Битовый Сдвиг вправо»: `>>`
128+
Побитовый сдвиг вправо сдвигает все цифры в числе на 1 ячейку вправо. Данный оператор дублирует первую цифру с левой части числа для того чтобы вставить ее в начало.
129+
130+
```js
131+
let num;
132+
133+
console.group('0b00000000000000000000000000000101')
134+
num = 0b00000000000000000000000000000101;
135+
console.log(num); // 5
136+
console.log(num >> 1); // 2 => 0b00000000000000000000000000000010
137+
console.log(num >> 2); // 1 => 0b00000000000000000000000000000001
138+
console.groupEnd();
139+
140+
console.group('0b11111111111111111111111111111010')
141+
num = -0b00000000000000000000000000000101; // 0b11111111111111111111111111111010 => -5
142+
console.log(num); // -5
143+
console.log(num >> 1); // -3 => 0b11111111111111111111111111111101
144+
console.log(num >> 2); // -2 => 0b11111111111111111111111111111110
145+
console.log(num >> 3); // -1 => 0b11111111111111111111111111111111
146+
console.groupEnd();
147+
```
148+
149+
## «Беззнаковый битовый сдвиг вправо»: `>>>`
150+
Данный оператор применяют когда нам нужно просто добавить `0` в начало числа, неважно какой до этого был знак у двоичного числа. Отрицательные числа всегда становятся положительными после использования данного оператора:
151+
152+
```js
153+
// Для положительных чисел ничего не поменялось
154+
let num;
155+
156+
console.group('0b00000000000000000000000000000101')
157+
num = 0b00000000000000000000000000000101;
158+
console.log(num); // 5
159+
console.log(num >> 1); // 2 => 0b00000000000000000000000000000010
160+
console.log(num >> 2); // 1 => 0b00000000000000000000000000000001
161+
console.groupEnd();
162+
163+
// Однако, для отрицательных чисел кое-что поменялось
164+
console.group('0b11111111111111111111111111111010')
165+
num = -0b00000000000000000000000000000101; // 0b11111111111111111111111111111010 => -5
166+
console.log(num); // -5
167+
console.log(num >>> 1); // 2147483645 => 0b01111111111111111111111111111101
168+
console.log(num >>> 2); // 1073741822 => 0b00111111111111111111111111111110
169+
console.log(num >>> 3); // 536870911 => 0b00011111111111111111111111111111
170+
console.groupEnd();
171+
```

public/posts/js-bit/js-bit-1.svg

Lines changed: 8 additions & 0 deletions
Loading

public/posts/js-bit/js-bit-2.svg

Lines changed: 8 additions & 0 deletions
Loading

public/posts/js-bit/js-bit-3.svg

Lines changed: 8 additions & 0 deletions
Loading

public/posts/js-bit/js-bit-4.svg

Lines changed: 8 additions & 0 deletions
Loading

public/posts/js-bit/js-bit-5.svg

Lines changed: 8 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)