Вы не спросили, была ли это хорошей идеей - как многие предположили, ваша выгода от такого сжатия пространства легко теряется в дополнительной обработке - но это другая тема :)
Вы также не упоминаете, где вы храните данные после. Каким бы ни было это место хранения/механизм, у него могут быть дополнительные условия и специализированные типы (например, база данных имеет формат двоичного столбца, может иметь формат столбца байтов, может даже поддерживать хранение битов и т. д.).
Но, придерживаясь темы, я думаю, что лучшее 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+a-z дает вам 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-битными или битовыми логическими решениями), но это усложняет ситуацию в долгосрочной перспективе - вероятно, больше проблем, чем того стоит.
person
Rudu
schedule
30.08.2010