Это своего рода простое сжатие, где вы используете одну числовую переменную для хранения множества логических / двоичных состояний, используя удвоение и тот факт, что каждое удваивающее число равно 1 + сумма всех предыдущих.
Я уверен, что это должна быть старая, хорошо известная техника, я хотел бы знать, как она называется, чтобы правильно на нее ссылаться. Я провел несколько поисков по каждому способу, которым могу придумать, чтобы описать это, но не нашел ничего, кроме некоторых статей в блогах, где авторы статей, кажется, сами это выяснили и тоже не знают, как это назвать ( пример 1 , пример 2 ).
Например, вот очень простая реализация, предназначенная для иллюстрации концепции:
packStatesIntoNumber () {
let num = 0
if (this.stateA) num += 1
if (this.stateB) num += 2
if (this.stateC) num += 4
if (this.stateD) num += 8
if (this.stateE) num += 16
if (this.stateF) num += 32
return num
}
unpackStatesFromNumber (num) {
assert(num < 64)
this.stateF = num >= 32; if (this.stateF) num -= 32
this.stateE = num >= 16; if (this.stateE) num -= 16
this.stateD = num >= 8; if (this.stateD) num -= 8
this.stateC = num >= 4; if (this.stateC) num -= 4
this.stateB = num >= 2; if (this.stateB) num -= 2
this.stateA = num >= 1; if (this.stateA) num -= 1
}
Вы также можете использовать побитовые операторы, разбор чисел с основанием 2, перечисления ... Есть много более эффективных способов реализовать это, меня интересует название подхода в более общем смысле.
источник
enums
, и они могут иметьFlags
атрибут. Они могут сделать ваш код намного проще.bool
обычно хранится как 32-битное целое число внутри. Таким образом, упаковка может иметь значение в 32 раза. Это действительно много. Я имею в виду, что мы, программисты, всегда готовы выбросить половину наших ресурсов, но я, как правило, не хочу выбрасывать 97% из них. Такие бесполезные факторы могут легко определить разницу между возможностью запуска важных сценариев использования и нехваткой памяти.Ответы:
Его чаще всего называют битовым полем , а другой термин, который вы часто будете слышать, это битовые маски , которые используются для получения или установки отдельных битовых значений или всего битового поля одновременно.
Многие языки программирования имеют вспомогательные структуры, чтобы помочь с этим. Как отмечает @BernhardHiller в комментариях, C # имеет перечисления с флагами ; У Java есть класс EnumSet .
источник
BitArray
, что позволяет хранить произвольное количество битов и индексировать их (в то время как флаги ограничены целочисленным типом и предназначены для использования в качестве масок).Странно, здесь довольно много разных терминов, но я не вижу того, что сразу пришло в голову (и это в названии вашего вопроса!) - Bit Packing - это то, что я всегда слышал, как его называли.
Я думал, что это действительно очевидно, но, как ни странно, когда я захожу в Google, это термин, который широко используется, но не определен официально (Википедия, кажется, перенаправляет на битовое поле, которое является способом упаковки битов, а не именем для процесс). Поиски определения, кажется, ведут к этой странице:
http://www.kinematicsoup.com/news/2016/9/6/data-compression-bit-packing-101
Это не очень хорошо для SO целей, но это лучшее определение / описание, которое я могу найти, включая это краткое описание: «Битовая упаковка - это простая концепция: используйте как можно меньше бит для хранения части данных».
источник
char
массива путем помещения двухchar
s в одинint
.Есть много разных терминов, используемых для описания этого.
Чаще всего биты называются «битовыми флагами» или «битовыми полями».
(Тем не менее, стоит отметить, что «битовые поля» иногда ссылаются на специфическую особенность языков C и C ++, которая связана, но не совсем одинакова.)
Само целое число по-разному называется «битовым массивом», «битовым набором» или «битовым вектором», в зависимости от использования и обстоятельств.
В любом случае извлечение битов из набора битов / вектора / массива осуществляется посредством сдвига и маскирования.
(т.е. используя битовую маску .)
Для некоторых примеров каждого термина в активном использовании:
std::bitset
BitSet
BitArray
bitvector
,bitarray
иbitset
bitarray
проект иBitVector
проектЭто не совсем относится к вопросу, но я хотел бы сказать: пожалуйста, не используйте сложение и вычитание для установки и очистки битов, так как эти методы подвержены ошибкам.
(т.е. если вы сделаете
num += 1
дважды, результат эквивалентенnum += 2
.)Вместо этого предпочтительнее использовать соответствующие побитовые операции, если выбранный вами язык обеспечивает их:
источник
this.stateF = (num & 32) ? true : false
и т. д. Не нужно изменятьnum
при извлечении значений.+
и-
. Теперь я стал лучше и использовал!= 0
вместо троичного, который, как мне кажется, более лаконичен, хотя еще и является expclit.