我编码和解码了一堆系数(与我之前的问题有关)。该过程基于RLE,其中对一堆系数进行编码,并且运行时编码仅关注零。简而言之,这就是原始数组:
[200, -145, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, -34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
编码成二进制数据,如下所示:
['000011001000', '11001>101101111<', '000010001110110011', '00010000111>1011110<', '00011000110011101', '000100011']
为了避免二进制数看起来像-10010001(-145),我手动对负数执行2补码(因为我找不到内置的方法)。在本例中,数字(-145,-34)的结果是(101101111,1011110)。为了避免混淆,我在上面的数组中标记了它们。
这被填充为能被8整除(最后一个元素的开头插入0),分成字节并写入文件。
当我读取文件时,我成功地解码了大部分内容,并且系数的数量与开始时相同。问题出现在负值上:
[200, 367, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
把-145改成了367,把-34改成了94。
是否有任何内置方法(或任何类型的方法)将位串转换为有符号值?我觉得这能解决我的问题。我没能找到一个方法,我现在卡住了。
对于无符号数,字长并不重要,因为前导零在那里没有意义。例如5=101
=0101
=00101
=0...0101
。然而,对于2的补码,字长是不同的,因为第一个位表示负数。例如,-3=101
!=0101
=5。如果您不知道第一个位是什么,则无法判断该数字是否为负。
似乎你的编码使用了可变的字宽。既然你已经可以解码这些数字,你就已经知道每个单词的宽度了。
# these variables should be set by your decoder
# in this case we read -145 encoded as 101101111
width = 9
word = 367
# add this to your decoder to fix the sign
firstBit = word >> (width - 1)
if (firstBit == 1):
leadingOnes = (-1 << width)
word = leadingOnes | word
同样可以在没有分支的情况下在单个语句中完成,但我认为这对于CPython来说平均会更慢,并且肯定会降低可读性。
word |= -(word >> (width - 1)) << width
当然,你必须确保非负数是用前导0
编码的,这样你就可以把它们和负数区分开来。