我电脑里虽也装著WINRAR,可是只用来解压,压缩功能几乎不用,因为压了跟没压差不多,有些视频格式压缩后反而比原件还大。


先上结论,1GB数据可以压缩至1MB。

是否可行取决于两个条件:

1.你要压缩的数据是什么?

2.你所使用的压缩演算法

假设我们只存储由可列印的ASCII字元组成的纯文本。我们将在知乎上设计我们自己的压缩演算法,我们可以叫它ZH-zip。

ZH-zip演算法将按照如下方式工作:

1) 指定一个字元

2) 此字元重复的次数指定为整数

3) 下划线(_)指定某字元串出现的次数

4)没有长度的下划线表示字元只使用一次。

5)文件末尾不需要下划线。

例如,"hello"压缩如下:

原文本: Hello.
压缩后: H_e_l2_o.

很明显这谈不上压缩,但是为了讲解起来方便点,举了上面的例子。

尝试压缩一些随机的字元串:

原文本: asdddffgggghhhhhjjjjjjkk
压缩后: a_s_d3_f2_g4_h5_j6_k2

可以看到我们刚刚设置的演算法将该文本的长度减少了3个字元。

对于下面这个字元串而言,我们直接将其缩减了一半:

源文本: AAAAABBBBBBABBBBBAAAAAAAABBBBBBB
压缩后: A5_B6_A_B5_A8_B7

32位元组被压缩为了16位元组。

现在如果你有一个1GB的「A」,即使用我们上述粗制滥造的压缩演算法,你也可以将其压缩到11位元组

Compressed: A1000000000

只要重复的字元串很长,我们的压缩率就会很高。

这能够实现吗?

很显然这取决于你所需要压缩的数据。

假设您是以无损格式存储游戏整个地图的屏幕截图。 大部分屏幕截图都是由图块组成的。 数十亿个相同的草砖一遍又一遍地重复,而数百万个相同的树也重复了。(类似红白机的采蘑菇和魂斗罗)

在这种情况下你的压缩效率将会变得很高。

1GB数据被压缩为1MB当然是可能的事情啦!


您好,可以的

#include &

int main(){
FILE *f = NULL;
f = fopen("E:\tmp.txt","w");
for(int i=0; i&<108000000; i++) { fputs("1111111111",f); } fclose(f); }

多压两次还能更小:


也可以用生成一个随机字元组成的txt:

#include &
#include &

int main(){
FILE *f = NULL;
f = fopen("E:\tmp rand.txt","w");
for(long long i=0; i&<1080000000; i++) { char x = rand(); fputc(x,f); } fclose(f); }

就完全压不动了


下面我现场表演一个将1TB数据压缩至几个位元组的示例。

这个方法的加解压速度非常快。

而且演算法能使用人类语言执行,易读性极强。

演示开始:

1TB全0。


宏观上说取决于数据的混乱程度,如果数据完全是随机生成的,极限压缩,也几乎压缩不了多少。

反之,如果数据比较有规律,规律性越强,则压缩空间越大。

可能把无限大的数据压缩成一行数据吗?可以。

举个例子,假如有这样一个文本文件:

135791113151719...

我们可以把它压缩成:

a[n+1] = a[n] + 2, a[0] = 1,

因为在上面的文件中,我们观察到其实是由一个等差数列连接而成的字元串,所以我们可以用通项公式来复现出文件的完整的信息。

再比如更一般的,文本文件中,往往每个字母的出现频率是不一样的,有的字母出现频率更高,有的则更低,如果我们尽可能的让出现频率更高的字母用更少的空间表示,这样就会达到一个数据压缩的效果,常见的典型例子就是哈夫曼编码 (Huffman Encoding)。

哈夫曼编码的原理是找到这么一种二进位编码模式,能让出现频率越高的字元用越短的二进位编码去表示,找到之后,进行编码,从而达到了一种压缩体积的效果,具体操作方法在这里不赘述。

也因为如此,哈夫曼编码能够对文本文件有不错的压缩效果,因为几乎所有文本文件的字元出现频率都是有差异的。

但也正因为如此,用哈夫曼编码去压缩图片,视频等文件,几乎起不到什么效果,因为以文字的角度去看图片文件,几乎可以看作是随机的乱码文件,字元出现的频率近乎一致。

上面所说的这种叫做无损压缩,能够保证压缩后的数据能够完整的复现成原来的数据,它更注重的是「变形」,利用数据已有的规律和特征,去进行一些变形,这本身不矛盾。

「内容「是抽象的,它包含著对我们人类有意义的信息,比如,文章,图片,但存储内容,必须有一个把内容变成数据的过程,数据比内容更为归一化,怎么理解这个归一化呢?不管是图片,还是文章,还是视屏,在 unix 系统下,它们都是以二进位文件的形式存储的,都是一堆 0 和 1,这就叫归一化,把多种内容编码成一种数据,给我们带来了很大的方便,我们只要想办法把数据以某种方式存储到物理介质上,我们就获得了存储所有「内容」的能力,这就像只要所有的网路I/O,文件I/O,块设备,字元设备,都能表现成对一个 fd 的读写,我们知道怎么对 fd 读写,我们就具备了操纵这么多种不同的 I/O 的能力,这个过程往往称之为编码,而数据在物理载体上的存储方式,则有无限种可能。

原来看到一篇科幻小说,好像是刘慈欣写的,说的是一个外星人,来了地球之后,把人类的所有知识都获取了之后,编码成了一串数字,大概就像这样:

28372493824923923..............很长很长...

然后这个外星人在第一数之后点了一个小数点,然后又加了个长度单位,索性就是米好了:

2.8372493824923923..............很长很长...m

由于这段数字虽然很长很长,但是它是有限的,而且这个外星人有很先进的度量能力,也就是说,他们有非常精密的尺子,即便是上面那么长,他们也能度量出来。

于是,外星人把上面那串数字当成了一段长度,在飞船上找了一个位置,准确的刻画了这段长度,于是,它就用这两个刻度,存储了地球的全部信息。

这听起来很神奇,你竟然能用一个刻度,存储地球的全部知识,当然在现实世界我们知道是不可能的,因为随著小数点后面的数变多,每个数代表的真实大小在指数级的减小,而对我们的衡量精度要求是指数级的增高,我们马上就无能为力了。

于此相同,我们还可以选取一个铁块,把上面的数字单位变成 kg,只要这个铁块的重量严格等于它,我们就用这个铁块,存储了人类的知识。

小学的数列找规律的题,就像是在寻找数据压缩的方式,如果你成功找到了通项公式,你就把这个无限长的数列压缩成了一个公式。

我在文章开头说的,数据的混乱程度,决定了数据压缩的难度,或者说,数据的熵越大,越难压缩,因为它缺乏可预测性,可归一性,没有同质化的区域,更没有可利用的规律,所以也缺乏被总结归纳的可能性。

再说说有损压缩,这方面就很好理解了,但是压缩的时候,往往要和内容紧密联系。

比如,内容是图片,我们压缩的时候,可能考虑降低解析度,把相邻的四个像素点取一个颜色平均值,然后变成一个像素点,这样,图片的解析度就被压缩成了原来的四分之一,但是看上去,还能看出原来的样子。

但是如果我们对文本文件做一摸一样的压缩处理,就会发现原来有意义的一篇文章变成了缩短四分之一后的奇怪乱码,这就是从内容的角度上,完全损失了数据。

而对于此,对于图片和文本,我们可以定义不同的压缩损失的函数,从而用来衡量压缩后信息的损失量。

图片具有稳定性,也就是说,将一个像素点的颜色微调一点,对整个图片不会有突变的印象,而对于文本,48 和 49 所代表的字元可能完全是两个字元,所以文本文件很难做有损压缩,而图片等多媒体资源,经常会做不同的压缩等级处理,比方说 720p,1080p,4k 等等。

而对于一堆在高维空间中的样本点来说,我们可以进行降维处理,比方说原有的数据点长这样:

然后你用把所有的数据点都投影在了蓝色的直线上,于是二维的样本点变成了一维的样本点,常见的方法有 PCA (Principle Component Analysis) 等。

谢谢!


其他答主理论说的不少了,我来实测一下。

用MATLAB写入一个全0(int8)的大小为1GB的二进位文件。

a = zeros(1,2^30,int8);
fid = fopen(D:1.bin,wb);
fwrite(fid,a);
fclose(fid);

验证一下是不是大小为1GB

file = dir(D:/1.bin);
isequal(file.bytes,2^30)

文件大小确实为1GB(2^30比特)

利用MATLAB的zip命令进行压缩,计算压缩文件大小为多少MB.

zip(D:1.zip,D:1.bin);
zipFile = dir(D:1.zip);
zipFile.bytes / 2^20

文件大小为0.9954MB,刚好小于1MB

ZIP文件的压缩率不高,尝试使用winrar进行压缩,压缩为rar文件。

!C:"Program Files"WinRARwinrar a D:1.rar D:1.bin
rarFile = dir(D:1.rar);
rarFile.bytes / 2^20

1.rar文件大小为0.0559MB

最后在Windows文件管理器看下各个文件的大小。

全部为0的1GB二进位文件,压缩为zip文件后刚好小于1M,rar文件则大约58KB


推荐阅读:
相关文章