Я пытаюсь закодировать два значения: «направление движения», которое может быть 0,1,2 или 3, и «направление взгляда», которое также может быть 0, 1, 2 или 3
Обобщением этого является битовое поле . Если вы посчитаете свой диапазон в двоичном коде, станет понятнее, как вы можете комбинировать свои значения:
(0).toString(2).padStart(8, 0); // = 00000000
(1).toString(2).padStart(8, 0); // = 00000001
(2).toString(2).padStart(8, 0); // = 00000010
(3).toString(2).padStart(8, 0); // = 00000011
Ваш диапазон использует два младших бита, поэтому для их кодирования по битам все, что вам нужно сделать, это СДВИГАТЬ одно из ваших значений в соседние два бита слева и ИЛИ два значения вместе. первая переменная использует биты 0,1, а вторая переменная использует биты 2,3.
const encodeC = (a, b) => (a << 2) | b;
Чтобы декодировать a
, мы просто меняем смещение на c
, больше ничего не нужно, так как b
отталкивается от конца правой части слова:
const decodeA = (c) => c >> 2;
Для декодирования b
нам нужно «замаскировать» его из c
, чтобы выбрать два младших бита и исключить все остальные, мы делаем это с AND (&
) 0b11
(3) :
const decodeB = (c) => c & 3;
Обратите внимание, что в приведенном выше примере гарантируется, что b
будет находиться в диапазоне 0-3, в противном случае он будет переполнен битами, зарезервированными для a
. a
с другой стороны, осталось еще 28 свободных битов, поэтому он может пойти намного выше.
Как уже упоминалось, с точки зрения распределения памяти все числа в JavaScript используют 64-битные (двойные) числа, которые временно преобразуются в 32-битные целые числа со знаком при выполнении побитовых операций. Это означает, что вы никогда не сможете использовать меньше памяти для одной переменной и использовать только до половины битов (32) для битовых полей.
Это не делает битовые поля недопустимыми в JavaScript, тем более, если, например, вы собираетесь выполнять дальнейшее кодирование в символ или что-то для отправки через AJAX. Вы можете использовать c.toString(36)
(0-36) или String.charFromCode(c + 32)
(0-95). Для использования 4 битов вам нужен только диапазон 0-15.
... Если вы кодируете в ASCII-символы, он действительно будет использовать один байт:)