2010-08-26 2 views
2

Моя PHP-программа работает с массивом значений от 0 до 7. Я пытаюсь найти наиболее эффективный способ сохранить эти значения в PHP. Наиболее эффективным я имею в виду использование меньшего количества бит.Хранение кучи двоичных данных длиной 3 бита с PHP

Понятно, что для каждого значения требуется только 3 бита пространства для хранения (b000 = от 0 до b111 = 7). Но каков наиболее эффективный способ хранения этих трехбайтовых значений в двоичной строке?

Я не знаю заранее, сколько 3 бит значений мне нужно будет хранить или восстанавливать, но это может быть много, поэтому 64 бит явно не хватает.

Я искал pack() и unpack(): я мог хранить два значения в каждом байте и использовать пакет ('C', $ twoValues), но я все еще теряю 2 бита.

Будет ли это работать? Существует ли более эффективный способ хранения этих значений?

Благодаря

+0

Вы не можете «хранить» вещи на PHP. Вы говорите об их сжатии в памяти во время работы с ними? Будете ли вы загружать их из базы данных? – meagar

+0

Да, я говорю о сжатии их в памяти, чтобы отправить их на мой механизм хранения, что бы это ни было. – analogue

ответ

1

Вы не спрашивали, если это была хорошая идея, - как предлагали многие, ваша выгода от такого рода пространства сжатия, легко теряется в дополнительной обработке - но это другая тема :)

Вы также не упоминая, где вы храните данные после. Независимо от того, какое место/механизм хранения может иметь дополнительные условия и специализированные типы (например, база данных имеет формат двоичного столбца, может иметь формат столбца в байте, может даже поддерживать хранение бит и т. Д.).

Но, придерживаясь темы, я думаю, что наилучшее 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); 

(Это эффективно, что Упаковать/Распаковать команды делают)

В качестве альтернативы вы можете кодировать символы, поскольку в 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; 

Ряд этих закодированных символов может быть сохранен как массив или строка с нулевым завершением.

ПРИМЕЧАНИЕ: В случае -say-64-битных целых чисел выше, мы сохраняем 3 бита в 4, поэтому получаем 64/4 = 16 мест хранения. Это означает, что мы откладываем еще 16 бит (1 за место), поэтому у вас может возникнуть соблазн добавить еще 5 значений, в общей сложности 21 (21 * 3 = 63 бит, только 1 потрачено впустую). Это, безусловно, возможно (с целочисленной математикой, хотя большинство экземпляров PHP не работают 64 бита или бит-логические решения), но это усложняет ситуацию в конечном итоге - вероятно, больше проблем, чем того стоит.

+0

Это именно то, что я сделал, но уродливым способом :) Спасибо – analogue

0

Я бы преобразовать каждое целое число в двоичную, сцепить все из них, а затем разделить полученную строку в байтах. Каждый байт будет 0-255, поэтому его можно сохранить как отдельный символ.

+0

Вы хотите сказать, что "каждый * байт * будет 0-255"? Бит может хранить только 2 значения. ^^ – gablin

+0

Приятный улов, как-то я всегда их смешиваю, даже после двойной проверки ... – Tim

1

Лучший способ хранить их как целые числа и не вмешиваться в упаковку вещей по частям. Если у вас нет реальной инженерной причины, вам нужно, чтобы они были сохранены как 3-битные значения (например, сопряжение с оборудованием), вы просто просите о головных болях. Имейте в виду, esp для нечетных размеров бит, они становятся довольно трудно иметь прямой доступ, если вы это сделаете. И если вы придерживаетесь этих значений в базе данных, вы не сможете искать или индексировать значения, упакованные таким образом. Храните их как целые числа, или если в db, возможно, короткое целое число или байт.

1

Такая техника необходима только в том случае, если у вас будет не менее полумиллиарда из них. Подумайте об этом, процессор должен будет иметь данные в одном регистре, маску в другой и AND, чтобы получить ваше значение. Теперь представьте себе повторение списка, который достаточно длинный, чтобы оправдать такую ​​технику экономии пространства. Сокращение пространства на 50% и на порядок медленнее.

0

Глядя на http://php.net/manual/en/language.types.php, вы должны хранить их как целые числа. Однако возникает вопрос, следует ли указывать одно целочисленное значение для многих трехбитовых значений или нет. Первый более сложный, но требует меньше памяти, тогда как первый - наоборот. Если у вас нет крайней необходимости уменьшать объем используемой памяти, я бы предложил последний (используйте одно целое для одного 3-битного значения).

Основная проблема с хранением многих трехбитовых значений в одном целочисленном состоянии - это выяснить, сколько из них 3-битовых значений. Вы можете использовать массив целых чисел, а затем иметь дополнительное целое число, в котором указано общее количество 3-битных значений. Однако, как также указано в руководстве, количество бит, используемых для целочисленного значения, зависит от платформы. Таким образом, вам нужно знать, является ли целое число 32 бита или 64 бита, иначе вы можете попытаться сохранить слишком много значений и потерять данные, или вы рискуете использовать больше памяти, чем необходимо (что было бы плохо, поскольку вы нацелились использовать как минимум память в первую очередь).