python - 打包数据,Python中的极端Bitpacking
问题描述
我需要将信息尽可能紧密地打包到比特流中。
我有不同数量的不同状态的变量:
Number_of_states=[3,5,129,15,6,2]# A bit longer in reality
我目前最好的选择是创建一个位域,使用
2+3+8+4+3+1 位 ->21 位
然而,应该可以将这些状态打包成np.log2(3*5*129*15*6*2)=18.4
位,节省两位。(实际上我有 298 位需要保存一些)
在我的情况下,这将节省大约 5% 以上的数据流,这将有很大帮助。
python中是否有可行的解决方案以这种方式打包数据?我试过packalgorithms
了,但它们只用几个字节的数据就产生了太多的开销。字符串没问题,它是常量,会提前传输。
这是我目前正在使用的代码:
from bitstring import pack
import numpy as np
DATA_TO_BE_PACKED=np.zeros(6)
Number_of_states=[3,5,129,15,6,2]#mutch longer in reality
DATA_TO_BE_PACKED=np.random.randint(Number_of_states)
string=''
for item in Number_of_states:
string+='uint:{}, '.format(int(np.ceil(np.log2(item))))
PACKED_DATA = pack(string,*DATA_TO_BE_PACKED)
print(len(PACKED_DATA ))
print(PACKED_DATA.unpack(string))
解决方案
您可以将状态解释为形状为 (3, 5, 129, 15, 6, 2) 的多维数组的索引。该索引可以编码为长度为 的扁平一维数组中的整数索引3*5*129*15*6*2 = 348300
。NumPy 具有可以为您执行此操作ravel_multi_index
的功能。unravel_index
例如,让num_states
您的状态的每个组件的状态数:
In [86]: num_states = [3, 5, 129, 15, 6, 2]
假设state
持有数据的一个实例;也就是说,它记录了每个组件的状态:
In [87]: state = [2, 3, 78, 9, 0, 1]
要编码此状态,请将其传递给ravel_multi_index
. idx
是编码状态:
In [88]: idx = np.ravel_multi_index(state, num_states)
In [89]: idx
Out[89]: 316009
通过构造,0 <= idx < 348300
,所以它只需要 19 位。
state
要从恢复idx
,请使用unravel_index
:
In [90]: np.unravel_index(idx, num_states)
Out[90]: (2, 3, 78, 9, 0, 1)
推荐阅读
- javascript - 模板 V 型槽内
在 vue 2.0.15 中不起作用 - sql-server - 传递查询的 from 子句中的语法错误
- javascript - GA 事件未在 JQuery 点击函数中触发
- kubernetes - 将运行状况检查主机标头添加到 Ingress
- javascript - 为 vue.js 分页的不同页面制作单独的 url
- python - 关于“for”循环的一般问题
- visual-studio - 无法从 Visual Studio 2017 连接到 Docker 上的远程调试器
- javascript - 如何解决“在短时间内调用过多次服务:exec qps。”
- javascript - CordovaJS - 错误:清单合并失败:uses-sdk:minSdkVersion 1 不能小于中声明的版本 19
- python - 在 pandas df 中查找每个类别的范围