压缩一个非常大的数字(在Python中)

时间:2013-08-03 22:53:13

标签: python numbers compression

我需要一个非常非常大的数字(143百万位)进行压缩。我正在寻找一种压缩它的解决方案,而不会损失至少10%。我已经尝试过zlib,zipfile,gzip等等,但这些都不会真正压缩这个数字。所以这是我的想法,但问题是我不知道如何实现它

首先,我有号码。

  

234512

然后我必须将它分成小于256的数字块。

  

234,51,2

如果尺寸固定(例如,总是3位数),我可以拆分它,但每块可能有1,2或3位数,所以我被困在这里。

在我得到小于256的数字块后,我会将它们变成字符并写入文件。

编辑:由于使用该方法我将失去着陆零,我创建了一个压缩数字大小的50%的算法:

  1. 由于我只有0-9个数字作为数字,我可以说它们是十六进制的(尽管它们不是)并转换为基数10,从而减小了它的大小。编辑2:跳过这一步。实际上,这样做只会增加它的大小!

  2. 我会得到一个较小的数字,0-9数字作为数字,然后我可以再次假设它们是十六进制的。因此,使用unhexlify将其转换为大量字节的一半! (如果它是奇数长度,在附加到数字处添加'a')

  3. 代码:

    if len(o)%2: o+='a' #avoid odd-length
    return unhexlify(o)
    

    我甚至可以用zlib压缩返回数据。总压缩率为45%。

1 个答案:

答案 0 :(得分:1)

这里是:

#! /usr/bin/python

n = 313105074639950943116 #just an example

#your algorithm
chars = []
buff = ''
s = str (n)
while s:
    if int (buff + s [0] ) < 256:
        buff += s [0]
        s = s [1:]
    else:
        chars.append (int (buff) )
        buff = ''
if buff: chars.append (int (buff) )

print ('You need to write these numbers converted to chars: {}'.format (chars) )
print ('This are {} bytes of data.'.format (len (chars) ) )
print ('But you cannot decompress it, because you lose leading zeros.')

chars = []
while n:
    chars.append (n & 0xff)
    n = n >> 8

print ('Now if you just write the number to a file without your algorithm:')
print ('You need to write these numbers converted to chars: {}'.format (chars) )
print ('This are {} bytes of data.'.format (len (chars) ) )
print ('And you can actually read it again.')

编辑:如果你的数字的十进制表示有很多6s和8s的序列,你应该尝试使用十进制表示的RLE,也许与霍夫曼树结合。

编辑2 :考虑(a)6s和8s的长时间运行,以及(b)你不想使用某些既定算法的事实,你可以使用这样一些非常粗略的RLE :

#! /usr/bin/python

n = 313666666666666688888888888888888866666666666666666666666666666610507466666666666666666666666666399509431888888888888888888888888888888888888888888881666666666666

s = str (n)
print (s)
comp = ''
count = None
while s:
    if s [0] in '01234579':
        if count:
            comp += ('<{}>' if count [0] == 6 else '[{}]').format (count [1] )
            count = None
        comp += s [0]
    if s [0] == '6':
        if count and count [0] == 6: count = (6, count [1] + 1)
        elif count:
            comp += ('[{}]').format (count [1] )
            count = (6, 1)
        else: count = (6, 1)
    if s [0] == '8':
        if count and count [0] == 8: count = (8, count [1] + 1)
        elif count:
            comp += ('<{}>').format (count [1] )
            count = (8, 1)
        else: count = (8, 1)
    s = s [1:]

if count: comp += ('<{}>' if count [0] == 6 else '[{}]').format (count [1] )

print (comp)