我有一个256 x 256的布尔数组。这些数组不断变化,设置位实际上是随机分布的。
我需要在请求时向许多客户端发送设置位的当前列表。
以下数字是近似值。
如果我发送每个设置位的坐标:
set bits data transfer (bytes)
0 0
100 200
300 600
500 1000
1000 2000
如果我发送距离(从左到右扫描)到下一个设定位:
set bits data transfer (bytes)
0 0
100 256
300 300
500 500
1000 1000
此稀疏阵列中设置的典型位数约为300-500,因此第二种解决方案更好。
有没有一种方法可以做得更好,而不会增加太多的处理开销?
答案 0 :(得分:2)
既然你说“实际上随机分布”,我们假设每个位置都是概率为p的伯努利试验。选择p来获得您期望的填充率。您可以将“跑步”(您的选项2)的长度视为获得成功所需的伯努利试验次数。事实证明,这一数量的试验遵循几何分布(概率为p)。 http://en.wikipedia.org/wiki/Geometric_distribution
到目前为止,您在选项#2中所做的是在每种情况下识别p的最大运行长度,并保留许多位以发送所有这些。请注意,这个最大长度仍然只是一个概率,如果真的非常不幸,方案将失败,并且所有位都在开头和结尾聚集。
正如@Mike Dunlavey在评论中所建议的,霍夫曼编码或其他形式的熵编码可以根据长度的频率重新分配所花费的比特。也就是说,短期运行更常见,因此使用较少的位来发送这些长度。此编码效率的理论限制是分布的“熵”,您可以在维基百科页面上查找,并评估不同的概率。在您的情况下,此熵范围从每次运行7.5位(1000个条目)到每次运行10.8位(100个)。
实际上,这意味着你不能做得比你目前为1000入场案件做得更好。 8位=每个值1个字节。对于100个条目的情况,您目前每次运行花费20.5位而不是理论上可能的10.8,因此该结束具有最高的改进机会。在300的情况下:我认为你没有保留足够的位来表示这些序列。熵是每像素9.23位,你当前正在发送8.你会发现许多情况,其中真空之间的空间超过256,这将溢出你的表示。
当然,所有这一切都假定事情确实是随机的。如果不是,则需要进行不同的熵计算。您可以随时使用直方图计算数据中的熵,并确定是否值得采用更复杂的选项。
最后,还要注意,现实生活中的熵编码器只能逼近熵。例如,Huffman coding必须为每个运行长度分配一个整数位。 Arithmetic coding可以分配小数位。