0

我需要以尽可能少的数据将以下内容转换为二进制格式(以及以后的恢复)。

my_arr = [
        [128,32 ,22,23],
        [104,53 ,21,25],
        [150,55 ,79,23],
        [104,101,23,8 ],
        [57 ,117,13,21],
        [37 ,135,21,20],
        [81 ,132,23,6 ],
        [81 ,138,7 ,8 ],
        [97 ,138,7 ,8 ]...

数字不超过 399

如果我为每个数字使用 0(连续 8 个 0 = 8)并使用 1 作为分隔符,第一行如下所示: 010010000000011000100110010011001000 这对于像 99 这样的数字来说真的很长

如果我将每个数字填充为三位数字并将每个数字依次转换为实际二进制,则第一行如下所示: 000100101000000000110010000000100010000000100011 每个数字有 12 个字符。

由于第一个字符永远不会是 4 或更高,我可以通过将 0 视为 00、1 视为 01、2 视为 10 和 3 视为 11 来保存两个数字。因此每个数字 10 个字符总的来说这将大小减小到大约 90% 的第一个选项(平均)但有更短的方法吗?

编辑:是的,作为 1 和 0 的字符串......它不需要比原始整数短......只是使用 2 个符号的最短可能编写方式

4

3 回答 3

5

如果这些值均匀分布在 0 到 399 之间,那么一个很好的编码方式是取三个值并将它们编码为一个以 400 为基数的三位整数。即 val1 + 400*val2 + 400*400*val3。然后该整数将很好地适合 26 位。四个连续的 26 位值将适合 13 个字节。然后你得到每个值的平均 13/12 字节。

除非值的分布有偏差,或者存在重复或相关性,否则您将能够做到这一点,在这种情况下,您可以进一步压缩它们。

处理细节,可以使用编码序列中的字节数来确定值的个数,可能不是三的倍数。如果它不是三的倍数,那么最后会有一个或两个值,每个值都简单地编码为九位。由于从 18 位到 26 位相加需要 8 位,因此计数没有歧义。

于 2013-01-13T23:36:43.127 回答
1

一个好的起点是创建由 1 和 0 组成的恒定长度块,这使您可以轻松解码字符串。

二进制中的 400 是 110010000,这需要 9 个字符来将每个数字编码为其二进制表示,零填充到恒定长度。

编码第一行:

var padTo9 = function( bin ){ 
    while( bin.length<9 ){ bin = "0" + bin; } 
    return bin; 
}
[128,32 ,22,23].map( function(i){ return padTo9( i.toString(2) ) }).join('');

/* result:
"010000000000100000000010110000010111"
*/

解码

"010000000000100000000010110000010111".match(/[0-1]{9}/g).map( function(i){ return parseInt( i, 2 ) });
/* result:
[128, 32, 22, 23]
*/

我认为获得更短字符串的唯一方法是使用可变块长度,这需要添加一些控制符号来告诉解码器以下数字以特定数量的字符编码。但是这些符号必须大于 400 并且仍然有 9 个字符长,所以我认为考虑到数据的随机分布,这无济于事。

于 2013-01-14T00:34:35.247 回答
0

max 399:2**9是(2**n)>=399的最小实例,每个数可以存储为9位;将每个转换为二进制,并连接

于 2021-12-14T14:55:34.903 回答