漢明碼(Hamming Code)原理及實現

漢明碼實現原理html


漢明碼(Hamming Code)是普遍用於內存和磁盤糾錯的編碼。漢明碼不只能夠用來檢測轉移數據時發生的錯誤,還能夠用來修正錯誤。(要注意的是,漢明碼只能發現和修正一位錯誤,對於兩位或者兩位以上的錯誤沒法正確和發現)。算法

 
漢明碼的實現原則是在原來的數據的插入k位數據做爲校驗位,把原來的N爲數據變爲m(m = n +k)位編碼。其中編碼時要知足如下原則:
2^- 1 >= m 其中(= n + k)
這就是Hamming不等式,漢明碼規定,咱們所獲得的m位編碼的2^k ( k>=0 && 2^k < m)位上插入特殊的校驗碼,其他位把源碼按順序放置。
 
漢明碼的編碼規則以下:
  • 在新的編碼的2^(k - 1)( k >= 0)位上填入0(即校驗位)
  • 把新的編碼的其他位把源碼按原順序填入
  • 校驗位的編碼方式爲:第k位校驗碼從則重新的編碼的第2^(k - 1)位開始,每計算2^(k - 1)位的異或,跳2^(k - 1)位,再計算下一組2^(k - 1)位的異或,填入2^(k - 1)位,好比:
    第1位校驗碼位於新的編碼的第1位(2 ^(1-1) == 1)(漢明碼從1位開始),計算1,3,5,7,9,11,13,15,...位的異或,填入新的編碼的第1位。
    第2位校驗碼位於新的編碼的第2位(2 ^(2-1) == 2),計算2,3,6,7,10,11,14,15,...位的異或,填入新的編碼的第2位。
    第3位校驗碼位於新的編碼的第4位(2 ^(3-1) == 4),計算4,5,6,7,12,13,14,15,20,21,22,23,...位的異或,填入新的編碼的第4位。
    第4位校驗碼位於新的編碼的第8位(2 ^(4-1) == 8),計算8-15,24-31,40-47,...位的異或,填入新的編碼的第8位。
    第5位校驗碼位於新的編碼的第16位(2 ^(5-1) == 16),計算16-31,48-63,80-95,...位的異或,填入新的編碼的第16位。
 
 
漢明碼編碼實例

以10101編碼爲例,建立一個漢明碼編碼的空間,而且把源碼填入編碼的對應位中中,_ _ 1 _ 0 10 _ 1,並留出校驗碼位(校驗位先設爲0)。(由於2^4 - 1>= 5+4 && 2^3 - 1 < 5+ 3因此須要4位校驗碼)
  • 計算校驗碼的第1位(1,3,5,7,9進行異或): 結果爲0,因此漢明碼第2^0位爲0,結果爲0 _ 1 _ 0 10 _ 1
  • 計算校驗碼的第2位(2,3,6,7進行異或): 結果爲0,因此漢明碼第2^1位爲0,結果爲001 _ 0 10 _ 1
  • 計算校驗碼的第3位(4,5,6,7進行異或): 結果爲1,因此漢明碼第2^2位爲0,結果爲0011 0 10 _ 1
  • 計算校驗碼的第4位(8, 9進行異或): 結果爲0,因此漢明碼第2^3位爲1,結果爲0011 0101 1
  • 因此最終編碼爲001101011.
 
 
漢明碼校驗錯誤實例

咱們以上面的編碼爲例,假設咱們如今收到的編碼爲001101001,咱們能夠發現漢明碼的第8位與原來的漢明碼001101011不一樣,那咱們怎麼找出這個第8位的錯誤編碼呢?
 
算法很簡單,咱們只要在算漢明碼校驗位的算法的上再算一遍,就獲得了漢明碼的校驗方法,好比計算001101001對應的2^k位。

1,3,5,7,9進行異或,獲得0測試

2,3,6,7進行異或,獲得0編碼

4,5,6,7進行異或,獲得0spa

8,9進行異或,獲得1code

咱們把上述結果反着排列,獲得1000,即十進制的8,根據漢明碼的校驗規則,編碼出錯的地方即在第8位,咱們把第8位的0換成1,便可得原來的編碼001101011。
 
上述的例子是出如今2^k的校驗位上的,若是出如今非2^k位上,獲得的結果也是同樣的,好比:
假設收到的編碼爲001100011,即第6位出了錯誤,咱們根據規則

1,3,5,7,9進行異或,獲得0htm

2,3,6,7進行異或,獲得1blog

4,5,6,7進行異或,獲得1內存

8,9進行異或,獲得0ci

咱們把上述結果反着排列,獲得0110,即十進制的6,根據漢明碼的校驗規則,編碼出錯的地方即在第6位,咱們把第6位的0換成1,便可得原來的編碼001101011。
 
漢明碼的編碼和校驗的C++實現

經過原理,咱們能夠很簡單地實現漢明碼的編碼和校驗代碼
編碼:
auto cal(size_t sz)->decltype(auto) { decltype(sz) k = 0; decltype(sz) cur = 1; while (cur - 1 < sz + k ) { cur <<= 1; k++; } return k; }
bool encode(const string &s, string &d) { d.clear(); auto k = cal(s.size()); d.resize(s.size() + k); for (decltype(d.size()) i = 0, j = 0, p = 0; i!= d.size();i++) { if ((i + 1) == pow(2,p) && p < k) { d[i] = '0'; p++; } else if (s[j] == '0' || s[j] == '1') d[i] = s[j++]; else 
            return false; } for (auto i = 0; i != k;i++) { int count = 0 ,index = 1 << i; for (auto j = index - 1; j < d.size() ;j += index) for (auto k = 0; k!= index && j < d.size(); k++, j++) count ^= d[j] - '0'; d[index - 1] = '0' + count; } return true; }
 
解碼與校驗:
auto antiCal(size_t sz)->decltype(auto) { decltype(sz) k = 0; decltype(sz) cur = 1; while (cur < sz) { cur <<= 1; k++; } return k; } auto decode(string &s, string &d)->decltype(auto) { s.clear(); auto k = antiCal(d.size()); s.resize(d.size() - k); decltype(d.size()) sum = 0; for (decltype(k) p = 0;p != k;p++) { int pAnti = 0; decltype(k) index = 1 << p; for (decltype(d.size()) i = index - 1;i < d.size(); i+=index) { for (auto j = 0; j < index && i < d.size(); i++, j++) pAnti ^= d[i] - '0'; } sum += pAnti << p; } if (sum != 0) d[sum - 1] = (1- (int)(d[sum - 1] - '0')) + '0'; for (decltype(d.size()) i = 0, p = 0,j = 0; i != d.size(); i++) { if ((i + 1) == (1 << p) && p < k) p++; else s[j++] = d[i]; } return sum; }

 

測試樣例:
int main() { string source, dest; while (cin >> source) { if (encode(source,dest)) { cout << "Source: " <<source << endl; cout << "Dest: " << dest << endl; } size_t index; cout << "----input error index : "; cin >> index; auto k = dest.size(); if (index != 0 && index <= dest.size()) dest[index - 1] = (1 - (int)(dest[index - 1] - '0')) + '0'; cout << "Code " << dest <<endl; auto ret = decode(source,dest); if (ret == 0) { cout << "Source: " <<source << endl; cout << "Dest: " <<dest << endl; } else { cout << "Error index "<< ret  << endl; cout << "Corret source: " <<source << endl; cout << "Corret dest: " <<dest << endl; } cout << endl; } return 0; } 10101 Source: 10101 Dest: 001101011
----input error index : 8 Code 001101001 Error index 8 Corret source: 10101 Corret dest: 001101011

1001010101010101010111111001101 Source: 1001010101010101010111111001101 Dest: 1111001101010100101010101111110101101 ----input error index : 20 Code 1111001101010100101110101111110101101 Error index 20 Corret source: 1001010101010101010111111001101 Corret dest: 1111001101010100101010101111110101101

1 Source: 1 Dest: 111 ----input error index : 0 Code 111 Source: 1 Dest: 111

 

參考資料:Calculating the Hamming Code

相關文章
相關標籤/搜索