Задать вопрос
AngryBot
@AngryBot
I am in love with Functional Programming.

Как понять и реализовать битовую карту?

Я как-то увидел, что можно реализовать хранение состояний того или иного субъекта с помощью битовой карты. То были состояния кнопки. Каждое состояние закодировано определённой степенью двойки. После записи "стартовых" состояний с ними можно проводить операции с помощью побитовых операторов javascript.

Component.State = {
  DISABLED: 1,
  FOCUSED: 2,
  HOVERED: 4,
  ACTIVE: 8,
  HAS_ICON: 16
}


Допустим, состояние HOVERED и FOCUSED будет записано как Component.State[HOVERED | FOCUSED]

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

Источники для ознакомления приветсвуются. Только не слишком сложные, потому что "академического" образования я не имею и мне, возможно, будет тяжело читать совсем научную литературу.
  • Вопрос задан
  • 1574 просмотра
Подписаться 2 Простой 2 комментария
Пригласить эксперта
Ответы на вопрос 5
hzzzzl
@hzzzzl
так будет нагляднее

states = {
  DISABLED: 0b001,   // так можно писать двоичные числа
  FOCUSED: 0b010,
  HOVERED: 0b100,
}

(states.DISABLED | states.HOVERED).toString(2)  // .toString(2) - переводит в двоичную
// "101"   // поставлены 1 и 3 биты
Ответ написан
Комментировать
wataru
@wataru Куратор тега Алгоритмы
Разработчик на С++, экс-олимпиадник.
| - это побитовое ИЛИ. & - побитовое И. Т.е. каждый разряд отдельно обрабатывается и, в случае ИЛИ, если хоть одно число имеет единицу в данном разряде, то и результат будет 1. Соответственно, 00001 | 00010 = 00011.

Степени двойки - это числа, где единица стоит только в одном бите. Если несколько таких чисел про-ИЛИ-ть - то получится число, где стоят единицы во всех нужных разрядах. Фактически, вы назначаете каждому состоянию свой разряд. Потом, где в числе стоят единицы - те состояния и есть.

Чтобы проверить, что бит в числе установлен, надо взять побитовое И и убедиться, что результат не 0 (он может быть либо 0 либо какой-то степенью двойки.
Ответ написан
Комментировать
samodum
@samodum
Какой вопрос - такой и ответ
Это не битовые карты, а битовые операции, маскирование.

Component.State = {
DISABLED: 1,
FOCUSED: 2,
HOVERED: 4,
ACTIVE: 8,
HAS_ICON: 16
}

Переводим всё в двоичные числа:
DISABLED: 00000001,
FOCUSED: 00000010,
HOVERED: 00000100,
ACTIVE: 00001000,
HAS_ICON: 00010000
Видишь как бит с единицей смещается?
Теперь применяем битовую операцию ИЛИ к выбранным значениям:
HOVERED | FOCUSED =
00000100 (4)
+
00000010 (2)
=
00000110 (6)
Мы смешали два значения и получили новое, в котором храним новое состояние.
Теперь, чтобы проверить, что в состоянии x=6 = 00000110 есть какое-то значение, нам надо проверить его битовой операцией И и сравнить с нулём:
Есть ли в x FOCUSED?
if (x & FOCUSED > 0) => есть, иначе нет: 00000110 & 00000100 = 00000100 > 0 => значение ЕСТЬ!

Есть ли в x DISABLED?
if (x & DISABLED > 0) => есть, иначе нет: 00000110 & 00000001 = 00000000 = 0 => значения НЕТ!
Ответ написан
@Karpion
Запись "HOVERED | FOCUSED" читается "HOVERED или FOCUSED". Однако, по-русски это должно говориться "HOVERED и FOCUSED" (аналог: крокодил - длинный и зелёный").
Ещё это выражение можно записать "HOVERED + FOCUSED" - будет то же самое, и к тому же понятнее. Но эта форма записи плоха тем, что для двух одинаковых признаков "HOVERED | HOVERED == HOVERED", а вот при сложении будет не так.

Допустим, переменная x содержит в себе статус кнопки. Работать с этой переменной надо так:
  • Кнопка попала в фокус: x|=FOCUSED
  • Кнопка вышла из фокуса: x&=~FOCUSED
  • Проверка, в фокусе ли кнопка: x&FOCUSED?в_фокусе:не_в_фокусе
Это можно использовать бездумно, не зная о двоичном представлении чисел.
Ответ написан
webdisigner
@webdisigner
это как распределение прав в админке
Например:
когда админ имеет права на:
чтение|запись|редактирование|создание|удаление
1|1|1|1|1
Переводим 11111 -> 31 (права супер юзера)

например обычный пользователь имеет права на только "чтение" то это будет выглядеть так:
1|0|0|0|0, где первая цифра и есть чтение (only read)
Переводим 10000 -> 16 (права обычного юзера)

И так далее по сумме определяешь кто есть кто
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
Rocket Смоленск
от 80 000 до 130 000 ₽
div. Ставрополь
от 40 000 до 90 000 ₽
Wanted. Санкт-Петербург
До 220 000 ₽
18 дек. 2024, в 11:57
500 руб./в час
18 дек. 2024, в 11:54
2000 руб./за проект