1即計算出所給數中包含1的個數
方法一:每一位分別異或(時間復雜度O(n)n代表數位數)
parity_check(unsigned x) { int val=0; unsigned int flag=1; while(flag) {
val^=(x&flag) flag=flag<<=1;//x左移一位 } return val&0x1;//取末位運算. val的二進制形式最后一位位1則返回1,為0則返回0. }
D ^= D >>4;
D ^= D >>2;
D ^= D >>1;
D&=1;
最后D就是偶校驗的值了。
可能有的同學一時之間看不明白算法的原理,這里解釋一下吧。
首先從D里面找兩個位D1和D0,而D1D0的偶校驗值E0=D1^D0,這個大家都明白的,然后D3和D2的檢驗值E1=D3^D2,同理還有E2=D5^D4以及E3=D7^D6;
E0=1時代表了D1和D0里面有奇數個1,E1、E2和E3同理;
然后復習一下小學數學:奇數*奇數=奇數,偶數*奇數=偶數
如果E0和E1里面有奇數個1,那么D3~D0里面就有奇數數個1,此時D3~D0的偶校驗值為1;
“如果E0和E1里面有奇數個1”這句話的意思不就是求由E1和E0組成的兩位二進制的偶校驗么?而且當E1E0的偶校驗值F0=1時,對應的D3~D0的偶校驗值也為1。
同理,E3E2的偶校驗值F1=1時,對應的D7~D4的偶校驗值也為1;
繼續同理,由F1和F0組成的兩位二進制的偶校驗G0=1時,對應的是E3~E0的偶校驗值為1,同時對應的D7~D0的偶校驗值為1。
於是求D7~D0的偶校驗值變成了求F1F0的偶校驗值。
那么首先就要將D7~D0的8個位兩兩分組后在分別求異或,然后再將得出的值的4個位兩兩分組后分別異或,最后將得出的值的2個位進行異或,得到的值就是D7~D0的偶校驗值了。
而分組則不必是相鄰的,將D右移4位再和原來的D進行異或的話就簡單多了
D7——D3
D6——D2
D5——D1
D4——D0
如此類推,每次先進行右移,然后和原來的值異或,最終就能得到D的校驗值了;另外在計算的過程中,僅僅需要關注后面的位數就可以了,如第二次計算時,高4位會有一些數據,到最后高7位也會有數據的,但這些數據都已經沒有用了,所以最后只需要來一個&1就可以l。
於是文章開頭的那段8位二進制數的算法為:
D ^= D >>4;
D ^= D >>2;
D ^= D >>1;
D&=1;
另外對於2^N位二進制數,第一次右移(2^N)/2位后再異或,然后重復類似的計算N次就可以了。