Вы не спросили, была ли это хорошая идея - как многие предполагали, ваша польза от такого типа сжатия пространства легко теряется при дополнительной обработке - но это уже другая тема:)
Вы также не упоминаете, где вы храните данные после. Независимо от того, какое расположение / механизм хранения может иметь дополнительные условия и специализированные типы (например, база данных имеет двоичный формат столбца, может иметь формат столбца байтов, может даже поддерживать хранение битов и т. Д.).
Но, придерживаясь темы, я предполагаю, что лучшее 3-битное хранилище - это кусочек (тянущий один бит), и я предполагаю, что я бы объединил два кусочка в байт (потеряв два бита в целом). Да, вы теряете два бита (если это ключ), но объединить два значения просто, поэтому затраты на обработку относительно невелики:
$byte=$val1*7+$val2;
$val2=$byte%7;$val1=($byte-$val2)/7;
Если байт недоступен, вы можете объединить их для получения 16 (4 сохраненных), 32 (8), 64 (16) целых чисел. Вы также можете сформировать массив этих значений для большего хранилища.
Я бы посчитал вышеупомянутое более понятным для человека, но вы также можете использовать битовую логику для объединения и разделения значений:
$combinedbyte=$val1<<3|$val2;
$val2=$combinedbyte&7;$val1=($combinedbyte&56)>>3);
(Это фактически то, что делают команды PACK / UNPACK)
В качестве альтернативы вы можете закодировать в символы, поскольку в ASCII первые несколько защищены, вы также можете начать с A (A-Z + 6 punc + az дает вам 58, когда вам нужно только 49 для хранения ваших двух значений).
$char=chr(($val1*7+$val2)+65); //ord('A')=65
$val2=(ord($char)-65)%7;$val1=(ord($char)-65-$val2)/7;
Последовательность этих закодированных символов может быть сохранена в виде массива или строки с нулевым символом в конце.
Примечание:
В случае 64-разрядных целых чисел, указанных выше, мы храним 3 бита в 4, поэтому получаем 64/4 = 16 мест хранения. Это означает, что мы добавляем еще 16 бит (1 на место), поэтому у вас может возникнуть желание добавить еще 5 значений, что в сумме составляет 21 (21 * 3 = 63 бита, только 1 потеряно). Это, конечно, возможно (с целочисленной математикой - хотя большинство экземпляров PHP не работают с 64-битными или битовыми логическими решениями), но это усложняет ситуацию в долгосрочной перспективе - возможно, больше проблем, чем стоит.