我電腦里雖也裝著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


推薦閱讀:
相关文章