講完校驗碼以後,你如今應該知道,不管是奇偶校驗碼,仍是CRC這樣的循環校驗碼,都只能告訴咱們一個事情,就是你的數據出錯了。因此,校驗碼也被稱爲檢錯碼(Error Detecting Code)。編碼
不論是校驗碼,仍是檢錯碼,在硬件出錯的時候,只能告訴你「我錯了」。可是,下一個問題,「錯哪兒了」,它是回答不了的。這就致使,咱們的處理⽅式只有一種,那就是當成「哪兒都錯了」。若是是下載一
個文件,發現校驗碼不匹配,咱們只能從新去下載;若是是程序計算後放到內存裏面的數據,咱們只能再從新算一遍。spa
這樣的效率實在是過低了,因此咱們須要有一個辦法,不只告訴咱們「我錯了」,還能告訴咱們「錯哪錯了」。因而,計算機科學家們就發明了 糾錯碼。糾錯碼須要更多的冗餘信息,經過這些冗餘信息,咱們不只
能夠知道哪兒的數據錯了,還能直接把數據給改對。這個是否是聽起來很神奇?接下來就讓咱們一塊兒來看一看。設計
最知名的糾錯碼就是海明碼。海明碼(Hamming Code)是以他的發明⼈Richard Hamming(理查德·海明)的名字命名的。這個編碼方式早在上世紀四十年代就被髮明出來了。一直到今天,咱們上一講所說到的
ECC內存,也還在使用海明碼來糾錯。blog
最基礎的海明碼叫 7-4海明碼。這裏的「7」指的是實際有效的數據,一共是7位(Bit)。而這裏的「4」,指的是咱們額外存儲了4位數據,用來糾錯。內存
首先,你要明一點點,糾錯碼的糾錯能力是有限的。不是說無論錯了多少位,咱們都能給糾正過來。否則咱們就不須要那7個數據位,只須要那4個校驗位就行了,這意味着咱們能夠不⽤數據位就能傳輸信息了。這就
不科學了。事實上,在7-4海明碼裏面,咱們只能糾正某1位的錯誤。這是怎麼作到的呢?咱們⼀起來看看。it
4位的校驗碼,一共能夠表示2^4=16個不一樣的數。根據數據位計算出來的校驗值,必定是肯定的。因此,若是數據位出錯了,計算出來的校驗碼,必定和肯定的那個校驗碼不一樣。那可能的值,就是在2^4-1=15
那剩下的15個可能的校驗值當中。效率
15個可能的校驗值,其實能夠對應15個可能出錯的位。這個時候你可能就會問了,既然咱們的數據位只有7位,那爲何咱們要用4位的校驗碼呢?用3位不就夠了嗎?2^3-1=7,正好可以對上7個不一樣的數據位啊!基礎
你別忘了,單比特翻轉的錯誤,不只可能出如今數據位,也有可能出如今校驗位。校驗位原本也是可能出錯的。因此,7位數據位和3位校驗位,若是隻有單比特出錯,可能出錯的位數就是10位,2^3-1=7種狀況是
不能幫咱們找到具體是哪一位出錯的。計算機科學
事實上,若是咱們的數據位有K位,校驗位有N位。那麼咱們須要知足下面這個不等式,才能確保咱們可以對單比特翻轉的數據糾錯。這個不等式就是:原理
在有7位數據位,也就是K=7的狀況下,N的最⼩值就是4。4位校驗位,其實最多能夠支持到11位數據位。我在下面列了一個簡單的數據位數和校驗位數的對照表,你能夠本身算一算,理解一下上面的公式。
如今你應該搞清楚了,在數據位數肯定的狀況下,怎麼計算須要的校驗位。那接下來,咱們就⼀起看看海明碼的編碼方式是怎麼樣的。
爲了算起來簡單一點,咱們少用一些位數,來算一個 4-3海明碼(也就是4位數據位,3位校驗位)。咱們把4位數據位,分別記做d一、d二、d三、d4。這裏的d,取的是數據位data bits的首字母。咱們把3位校驗位,
分別記做p一、p二、p3。這⾥的p,取的是校驗位parity bits的首字母。
從4位的數據位裏面,咱們拿走1位,而後計算出一個對應的校驗位。這個校驗位的計算用以前講過的奇偶校驗就能夠了。好比,咱們用d一、d二、d3來計算出一個校驗位p1;用d一、d三、d4計算出⼀個校驗位p2;用
d二、d三、d4計算出一個校驗位p3。就像下面這個對應的表格同樣:
這個時候,你去想想,若是d1這一位的數據出錯了,會發生什麼狀況?咱們會發現,p1和p2和校驗的計算結果不同。d2出錯了,是由於p1和p3的校驗的計算結果不同;d3出錯了,則是由於p2和p3;若是
d4出錯了,則是p一、p二、p3都不同。你會發現,當數據碼出錯的時候,至少會有2位校驗碼的計算是不一致的。
那咱們倒過來,若是是p1的校驗碼出錯了,會發⽣什麼狀況呢?這個時候,只有p1的校驗結果出錯。p2和p3的出錯的結果也是同樣的,只有一個校驗碼的計算是不一致的。
因此校驗碼不一致,一共有2^3-1=7種狀況,正好對應了7個不一樣的位數的錯誤。我把這個對應表格也放在下面了,你能夠理解一下。
能夠看到,海明碼這樣的糾錯過程,有點兒像電影裏面看到的推理探案的過程。經過出錯現場的額外信息,一步一步條分縷析地找出,究竟是哪一位的數據出錯,還原出錯時候的「犯罪現場」。看到這裏,相信你一方面會以爲海明碼特別神奇,可是同時也會冒出一個新的疑問,咱們怎麼才能用一套程序或者規則來生成海明碼呢?其實這個步驟並不複雜,接下來咱們就一塊兒來看一下。
首先,咱們先肯定編碼後,要傳輸的數據是多少位。好比說,咱們這裏的7-4海明碼,就是⼀共11位。而後,咱們給這11位數據從左到右進行編號,而且也把它們的二進制表示寫出來。
接着,咱們先把這11個數據中的二進制的整數次冪找出來。在這個7-4海明碼裏面,就是一、二、四、8。這些數,就是咱們的校驗碼位,咱們把他們記錄作p1~p4。若是從⼆進制的⻆度看,它們是這11個數當中,惟
四的,在4個比特里面只有一個比特是1的數值。那麼剩下的7個數,就是咱們d1-d7的數據碼位了。
而後,對於咱們的校驗碼位,咱們仍是用奇偶校驗碼。可是每個校驗碼位,不是用全部的7位數據來計算校驗碼。兒是p1用三、五、七、九、11來計算。也就是,在二進制表示下,從右往左數的第四位比特是1的狀況
下,用p1做爲校驗碼。
剩下的p2,咱們用三、六、十、11來計算校驗碼,也就是在二進制表示下,從右往左數的第二位比特是1的狀況下,用p2。那麼,p3天然是從右往左數,第三位比特是1的狀況下的數字校驗碼。而p4則是第四位比特是
1的狀況下的校驗碼。
這個時候,你會發現,任何一個數據碼出錯了,就至少會有對應的兩個或者三個校驗碼對不上,這樣咱們就能反過來找到是哪個數據碼出錯了。若是校驗碼出錯了,那麼只有校驗碼這一位對不上,咱們就知道是這
個校驗碼出錯了。
上面這個方法,咱們能夠用一段肯定的程序表示出來,意味着不管是幾位的海明碼,咱們都再也不須要人工去精巧地設計編碼方案了。
其實,咱們還能夠換一個角度來理解海明碼的做用。對於兩個二進制表示的數據,他們之間有差別的位數,咱們稱之爲海明距離。好比1001和0001的海明距離是1,由於他們只有最左側的第⼀位是不一樣的。而1001
和0000的海明距離是2,由於他們最左側和最右側有兩位是不一樣的。
因而,你很容易能夠想到,所謂的進行一位糾錯,也就是全部和咱們要傳輸的數據的海明距離爲1的數,都能被糾正回來。
而任何兩個實際咱們想要傳輸的數據,海明距離都至少要是3。你可能會問了,爲何不能是2呢?由於若是是2的話,那麼就會有一個出錯的數,到兩個正確的數據的海明距離都是1。當咱們看到這個出錯的數的時
候,咱們就不知道究竟應該糾正到那一個數了。
在引如了海明距離以後,咱們就能夠更形象地理解糾錯碼了。在沒有糾錯功能的狀況下,咱們看到的數據就好像是空間裏面的一個一個點。這個時候,咱們可讓數據之間的距離很緊湊,可是若是這些點的座標稍稍
有錯,咱們就可能搞錯是哪個點。
在有了1位糾錯功能以後,就好像咱們把一個點變成了以這個點爲中心,半徑爲1的球。只要座標在這個球的範圍以內,咱們都知道實際要的數據就是球⼼的座標。而各個數據球不能距離太近,不一樣的數據球之間要有
3個單位的距離。
好了,糾錯碼的內容到這⾥就講完了。你可不要⼩看這個看起來簡單的海明碼。雖然它在上世紀40年代早早地就誕生了,不過直到今天的ECC內存裏面,咱們還在使用這個技術方案。而海明也由於海明碼得到了圖靈獎。
經過在數據中添加多個冗餘的校驗碼位,海明碼不只可以檢測到數據中的錯誤,還可以在只有單個位的數據出錯的時候,把錯誤的一位糾正過來。在理解和計算海明碼的過程當中,有一個很重要的點,就是不只原來的
數據位可能出錯。咱們新添加的校驗位,同樣可能會出現單比特翻轉的錯誤。這也是爲何,7位數據位用3位校驗碼位是不夠的,而須要4位校驗碼位。
實際的海明碼編碼的過程也並不複雜,咱們經過不不一樣過的校驗位,去匹配多個不一樣的數據組,確保任何一個數據位出錯,都會產生意個多個校驗碼位出錯的惟一組合。這樣,在出錯的時候,咱們就能夠反過來找到
出錯的數據位,並糾正過來。當只有一個校驗碼位出錯的時候,咱們就知道實際出錯的是校驗碼位了。