我的PHP程序正在处理从0到7的值数组。我正在尝试找到在PHP中存储这些值的最有效方法。最有效的意思是使用较少的位数。
很明显,每个值只需要3位存储空间(b000 = 0到b111 = 7)。但是,将这些3位值存储在二进制字符串中的最有效方法是什么?
我事先并不知道我需要存储或恢复多少3位值,但它可能很多,所以64位显然是不够的。
我正在研究pack()和unpack():我可以在每个字节中存储两个值并使用一个包('C',$ twoValues),但我仍然在丢失2位。
会起作用吗?是否有更有效的方法来存储这些值?
由于
答案 0 :(得分:1)
最好的方法是将它们存储为整数,而不是一点一点地打包。除非你有实际的工程原因,你需要将它们存储为3位值(例如,与硬件接口),否则你只是要求头痛。请记住,特别是对于奇数位大小,如果你这样做,它们变得非常难以直接访问。如果您将这些值保留在数据库中,您将无法搜索或索引像这样打包的值。将它们存储为整数,或者如果在db中,可能是一个短整数或字节。
答案 1 :(得分:1)
这种技术只有在你拥有至少5亿这些技术时才是必要的。考虑一下,CPU必须将数据放在一个寄存器中,将掩码放在另一个寄存器中,然后使用AND来获取您的值。现在想象一下迭代这些足够长的证据来证明这种节省空间的技术。空间减少50%,速度慢一个数量级。
答案 2 :(得分: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,当你只需要49来存储你的两个值时,它给你58)。
$char=chr(($val1*7+$val2)+65); //ord('A')=65
$val2=(ord($char)-65)%7;$val1=(ord($char)-65-$val2)/7;
一系列这些编码字符可以存储为数组或以空终止字符串形式存储。
注意: 在上面的-say-64位整数的情况下,我们在4中存储3位,因此得到64/4 = 16个存储位置。这意味着我们要再加16个位(每个位置1个),因此您可能想要添加另外5个值,总共21个(21 * 3 = 63位,只浪费1个)。这当然是可能的(使用整数数学 - 虽然大多数PHP实例不能工作@ 64位,或位逻辑解决方案)但从长远来看它会使事情变得复杂 - 可能比它的价值更麻烦。
答案 3 :(得分:0)
我会将每个整数转换为二进制,连接所有整数,然后将结果字符串拆分为字节。每个字节为0-255,因此可以存储为单个字符。
答案 4 :(得分:0)
查看http://php.net/manual/en/language.types.php,您应该将它们存储为整数。但是,问题是是否让一个整数值代表许多3位值。前者更复杂但需要的内存更少,而第一种则相反。如果您没有极端需要减少使用的内存量,那么我建议使用后者(对一个3位值使用一个整数)。
将许多3位值存储在一个整数中的主要问题是确定有多少3位值。您可以使用整数数组,然后使用一个额外的整数来表示3位值的总数。但是,如手册中所述,用于整数值的位数取决于平台。所以你必须知道一个整数是32位还是64位,否则你可能会尝试存储太多的值并丢失数据,或者你冒着比所需更多的内存的风险(当你瞄准时这将是一件坏事)首先使用少量内存。)