压缩Python

时间:2016-07-16 00:43:06

标签: python list memory compression

我有一个具有以下属性的正(随机)整数列表:

元素数量:78495

元素的最大值:999982

转换为字符串时的列表长度:517115(字符串看起来像" 6,79384,238956,...")

磁盘上文本文件中列表的大小:520 kb

我正在尝试将此列表用作在线判断问题的预先计算列表,因为实际生成此列表需要很长时间。但是,如果我将它直接粘贴到源代码中,它的大小不能被接受,源代码的上限为50 kb。

我将zlib作为一种压缩字符串的方法,但它似乎只是缩小了一半。

有没有办法真正缩小它,所以我可以解压缩它/在源代码中使用它?

4 个答案:

答案 0 :(得分:3)

鉴于你的定义......

它是最小k值的列表,其中10 ^ k = 1 mod p for primes p> 5

...我错误地认为您的值的格式为(p - 1) / x,其中x是一个明显小于p的整数?

例如,对于p < 50,我们有:

p = 7  : 10^6  = 1 (mod 7)  => k = 6  = (p - 1) / 1  => x = 1
p = 11 : 10^2  = 1 (mod 11) => k = 2  = (p - 1) / 5  => x = 5
p = 13 : 10^6  = 1 (mod 13) => k = 6  = (p - 1) / 2  => x = 2
p = 17 : 10^16 = 1 (mod 17) => k = 16 = (p - 1) / 1  => x = 1
p = 19 : 10^18 = 1 (mod 19) => k = 18 = (p - 1) / 1  => x = 1
p = 23 : 10^22 = 1 (mod 23) => k = 22 = (p - 1) / 1  => x = 1
p = 29 : 10^28 = 1 (mod 29) => k = 28 = (p - 1) / 1  => x = 1
p = 31 : 10^15 = 1 (mod 31) => k = 15 = (p - 1) / 2  => x = 2
p = 37 : 10^3  = 1 (mod 37) => k = 3  = (p - 1) / 12 => x = 12
p = 41 : 10^5  = 1 (mod 41) => k = 5  = (p - 1) / 8  => x = 8
p = 43 : 10^21 = 1 (mod 43) => k = 21 = (p - 1) / 2  => x = 2
p = 47 : 10^46 = 1 (mod 47) => k = 46 = (p - 1) / 1  => x = 1

x值列表应比k值列表压缩得更好。 (例如,我愿意打赌,x的最常见值将是'1'。)

因为计算高达100万的素数(我认为是你的上限)相当容易和快速,你可以根据压缩的x值列表和真实值快速重建k值列表。时间计算的素数列表。

你可能应该从一开始就解释你究竟想要压缩什么来获得更准确的答案。

答案 1 :(得分:1)

简而言之,没有。

log(2, 999982) ~= 20

所以最大的数字需要20位才能存储。让我们说平均而言,每个数字需要10位来存储(均匀分布在0和最大值之间)。

~80,000 numbers * 10 bits per number = 800,000 bits = 100,000 bytes

因此,尽可能有效地存储这些数字将需要大约100KB的空间。

只有在数字有一些非随机性的情况下,压缩才有效。如果它们真的是随机的,正如你所说的那样,那么一般的压缩算法就无法让它变得更小,所以100KB就是你所希望做的最好的。

修改

请注意,事情更糟糕,因为您希望将这些内容粘贴到源代码中,因此您无法使用任意二进制数据。你需要一些文本友好的东西,比如base64编码,这将增加另外约33%的开销。此外,您无法根据所需的平均位数来存储数字,因为您需要某种方式来了解每个数字所使用的位数。有可能的编码方案,但都会带来一些额外的开销。

第二次编辑

根据上述评论,数据实际上是随机的。因此,一般压缩算法可能工作,如果没有,可能会有其他解决方案(例如,只提供首先生成数字的代码,可能小于50KB)。

答案 2 :(得分:1)

best text compression可用提供(大约)12-17%的压缩率(62.4-90 kB),因此您无法达到阈值。您的数据也是随机的,这通常会使压缩算法的性能更差。

看看另一种方法,例如让您的RNG流程更快,或者如果您不需要完整列表(只是一些整数),请创建一个单独的&#34;生产者&#34;线程生成随机整数(涉及你正在使用的任何实际数学)和一个&#34;消费者&#34;当这些整数进入时,它会对这些整数起作用。这样,即使生成完整列表需要很长时间,你的程序仍然可以正常工作。

答案 3 :(得分:0)

在这里,我已经在python上的两个字符串上测试了易于使用的算法:一个是随机生成的,分布不均匀,另一个是具有某种结构的。看来,lzma表现更好

# check the compression ratio
import lzma
import zlib
import gzip
import bz2
import zipfile
import tarfile
compressors = ['lzma','zlib','gzip','bz2'] 
a = np.exp(np.random.rand(1024))
b = np.arange(1024)
b[32] = -10
b[96] = 20000
a = bytes(a)
b = bytes(b)

for i in range(len(compressors)):
    print("{} compression ratio: ".format(compressors[i]))
    a_lzma = eval(compressors[i]).compress(a)
    b_lzma = eval(compressors[i]).compress(b)
    print(float(len(a_lzma))/len(a),float(len(b_lzma))/len(b))
    print("\n")

输出:

  lzma压缩率:   0.93115234375 0.08984375

     

zlib压缩率:   0.95068359375 0.1944580078125

     

gzip压缩率:   0.9521484375 0.196533203125

     

bz2压缩率:   0.9925537109375 0.1268310546875