zigzag壓縮演算法

2021-08-29 01:14:15 字數 2524 閱讀 5788

前文 base 128 varints 編碼(壓縮演算法) 介紹了base 128 varints這種對數字傳輸的編碼,了解到了這種編碼方式是為了最大程度壓縮數字的。但是,在前文裡,我們只談論到了正數的情況,那如果出現了負數,該怎麼辦?zigzag壓縮演算法解決的就是這個問題。

在聊這個演算法之前,我們得先補補課,聊聊二進位制補碼相關的東東。

我們知道,計算機儲存的資料都是二進位制的01串,而數字的01串又是以補碼的形式儲存的,補碼是什麼東西?為什麼要用補碼?下面我們乙個個來看:

要了解補碼,首先要了解原碼。

什麼是原碼?簡單點說,就是把十進位制轉為二進位制的表示形式,我們用第乙個位表示符號(0為非負數,1為負數),剩下的位表示值。比如:

[+8] = [00001000]原

[-8] = [10001000]原

我們用第一位表示符號(0為非負數,1為負數),剩下的位,非負數保持不變,負數按位求反。比如:

[+8] = [00001000]原 = [0000 1000]反

[-8] = [10001000]原 = [1111 0111]反

就是說:正數的反碼是本身,負數的反碼保持符號位不變,其他位逐位取反

首先,我們來看為什麼會出現補碼,我們先來看2個問題

第一,0居然用2個編碼(+0和-0)來表示了:

原碼:[0000 0000]原 = [1000 0000]原

反碼:[0000 0000]反 = [1111 1111]反

第二,我們來看乙個現象

1 + (-1)

= [00000001]原 + [1000 0001]原

= [10000010]原

= -2

明顯是不對的!

反碼:1 + (-1)

= [00000001]反 + [1111 1110]反

= [1111 1111]反

= -0

表現的好詭異!(正常應該是 0000 0000)

為了解決這些問題,我們在計算機體系中引入了補碼。

現在我們來看補碼怎麼取:

我們用第一位表示符號(0為非負數,1為負數),剩下的位非負數保持不變,負數按位求反末位加一。

[+8] = [00001000]原 = [0000 1000]補

[-8] = [10001000]原 = [1111 0111]反 = [1111 1000]補

即:正數的補碼是自己本身,負數的補碼口訣為:逐位取反,末位加1

引進了補碼之後,我們看看計算的情況:

1 + (-1)

= [00000001]補 + [1111 1111]補

= [0000 0000]補

= 0很明顯,通過這樣的方式,計算機進行運算的時候,就不用關心符號這個問題,而只需要按照統一的逢二進一的原則進行運算就可以了。

好了,補充了這些知識之後,可以進入正題了。

前文說到了,在絕大多數情況下,我們使用到的整數,往往是比較小的。然而,我們為了正確,又不得不把很多無用的0進行傳輸。base 128 varints編碼很好地解決了上面說的問題,但是,如果傳輸的數字出現了負數,會出現什麼情況呢?

依然舉個很簡單的例子,假設我要傳輸數字-1,會怎樣傳輸呢?

[-1]=[10000000 00000000 00000000 00000001]原 = [11111111 11111111 11111111 11111110]反 = [11111111 11111111 11111111 11111111]補

前面的廢物0,到這裡居然變成了廢物1了,怎麼樣才能進行壓縮呢?

zigzag給出了乙個很巧的方法:我們之前講補碼講過,補碼的第一位是符號位,他阻礙了我們對於前導0的壓縮,那麼,我們就把這個符號位放到補碼的最後,其他位整體前移一位

-1= [11111111_11111111_11111111_11111111]補= [11111111_11111111_11111111_11111111]符號後移

但是即使這樣,也是很難壓縮的,因為數字絕對值越小,他所含的前導1越多。於是,這個演算法就把負數的所有資料位按位求反,符號位保持不變,得到了這樣的整數:

-1= [11111111_11111111_11111111_11111111]補= [11111111_11111111_11111111_11111111]符號後移=[00000000_00000000_00000000_00000001]符號後移

我們熟悉的前面的一堆0又出現了,又可以愉快地使用base 128 varints演算法進行編碼了。

那麼,如果是正數的情況,這個演算法改怎麼處理呢?如果數字是正數,符號位一樣放到最後,其他資料全部保持不變就行了,例如:

[1]= (00000000_00000000_00000000_00000001)補

= (00000000_00000000_00000000_00000010)符號後移

= (00000000_00000000_00000000_00000010)zigzag

這樣一弄,正數、0、負數都有同樣的表示方法了,我們就可以對小整數進行壓縮了

zigzag相關題目

題目 輸入n 求乙個n n的矩陣,規定矩陣沿45度角線遞增,形成乙個zigzag陣列,請問如何用c 實現 如圖 please input the number 80 1 5 6 14 15 27 282 4 7 13 16 26 29 423 8 12 17 25 30 41 439 11 18 2...

zigzag遍歷矩陣

按之字型遍歷乙個矩陣。之字形遍歷順序如下圖所示 處理乙個二維矩陣一定不能陷入繁瑣的細節處理中,如果此題思考方向為到了 2 後如何轉向 5,到了 5 後如何轉向 9,到了 9 後又如何轉向 6,這樣程式設計會變得異常複雜。應該抽象出子過程,本題的子過程就是遍歷矩陣斜著的一行,只不過每隔一行遍歷方向改變...

FOR壓縮演算法

倒排表的壓縮演算法 for rbm 詞項索引的檢索原理 fst 如上圖,假設倒排表中最理想的一行id為1,2,3.100 w個連續數字 圖 若沒有使用for壓縮演算法,則有100w個int型別的數字,1數字 4位元組,則有400w位元組,約佔4m儲存空間。1位元組 8bit,則1int需要32bit...