2

我的 PHP 程序正在处理从 0 到 7 的值数组。我试图找到在 PHP 中存储这些值的最有效方法。最有效的意思是使用更少的位数。

很明显,每个值只需要 3 位存储空间(b000=0 到 b111=7)。但是将这些 3 位值存储在二进制字符串中的最有效方法是什么?

我事先不知道需要存储或恢复多少个 3 位值,但可能很多,因此 64 位显然是不够的。

我正在研究 pack() 和 unpack():我可以在每个字节中存储两个值并使用一个 pack('C', $twoValues),但我仍然丢失了 2 位。

它会起作用吗?有没有更有效的方法来存储这些值?

谢谢

4

5 回答 5

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);

(这实际上是 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;

一系列这些编码字符可以存储为数组或以空字符结尾的字符串。

注意:在上面的 -say- 64 位整数的情况下,我们将 3 位存储在 4 中,因此得到 64/4=16 个存储位置。这意味着我们要再增加 16 个位(每个位置 1 个),因此您可能会想再添加 5 个值,总共 21 个(21*3=63 位,仅浪费 1 个)。这当然是可能的(使用整数数学 - 尽管大多数 PHP 实例在 64 位或位逻辑解决方案中不起作用),但从长远来看它会使事情复杂化 - 可能比它的价值更麻烦。

于 2010-08-30T16:15:46.900 回答
1

最好的方法是将它们存储为整数,而不是一点一点地打包。除非您有实际的工程原因需要将它们存储为 3 位值(例如,与硬件接口),否则您只是在自找麻烦。请记住,特别是对于奇数位大小,如果您这样做,它们将变得非常难以直接访问。如果您将这些值保存在数据库中,您将无法搜索或索引像这样打包的值。将它们存储为整数,或者如果在数据库中,可能是一个短整数或字节。

于 2010-08-26T21:54:04.780 回答
1

只有当你至少拥有十亿个这样的技术时,才需要这种技术。想一想,CPU 必须在一个寄存器中保存数据,在另一个寄存器中保存掩码,然后将它们与它们相结合,以获取您的值。现在想象一下迭代一个足够长的列表来证明这种节省空间的技术是合理的。空间减少了 50%,速度降低了一个数量级。

于 2010-08-26T21:59:21.277 回答
0

我会将每个整数转换为二进制,连接所有整数,然后将生成的字符串拆分为字节。每个字节将是 0-255,因此可以将其存储为单个字符。

于 2010-08-26T21:50:30.677 回答
0

查看http://php.net/manual/en/language.types.php,您应该将它们存储为整数。然而,问题是是否让一个整数值代表许多 3 位值。前者更复杂但需要更少的内存,而第一个则相反。如果您没有极端需要减少使用的内存量,那么我建议后者(一个整数用于一个 3 位值)。

在一个整数中存储许多 3 位值的主要问题是弄清楚有多少个 3 位值。您可以使用一个整数数组,然后有一个额外的整数来说明 3 位值的总数。但是,正如手册中所述,用于整数值的位数取决于平台。因此,您必须知道整数是 32 位还是 64 位,否则您可能会尝试存储太多值并丢失数据,或者您可能会使用比需要更多的内存(这将是一件坏事,因为您的目标是首先使用尽可能少的内存)。

于 2010-08-26T21:59:46.900 回答