漢明權重

漢明權重是一串符號中非零符號的個數。因此它等同於同樣長度的全零符號串的漢明距離。在最為常見的資料位符號串中，它是1的個數。歷史及應用.漢明權重是以理查德·衛斯里·漢明的名字命名的，它在包括資訊理論、編碼理論、密碼學等多個領域都有應用。高效實現.在密碼學以及其它應用中經常需要計算資料位中1的個數，針對如何高效地實現人們已經廣泛地進行了研究。一些處理器使用單個的命令進行計算，另外一些根據資料位向量使用並行運算進行處理。對於沒有這些特性的處理器來說，已知的最好解決辦法是按照樹狀進行相加。例如，要計算二進位制數A=0110110010111010中1的個數，這些運算可以表示為：這裡的運算是用C語言表示的，所以X » Y表示X右移Y位，X &amp; Y表示X與Y的位與，+表示普通的加法。基於上面所討論的思想的這個問題的最好演算法列在這裡：//types and constants used in the functions belowtypedef unsigned __int64 uint64; //assume this gives 64-bitsconst uint64 m1 = 0x5555555555555555; //binary: 0101...const uint64 m2 = 0x3333333333333333; //binary: 00110011..const uint64 m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ...const uint64 m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones ...const uint64 m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...const uint64 m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones ...const uint64 hff = 0xffffffffffffffff; //binary: all onesconst uint64 h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...//This is a naive implementation, shown for comparison,//and to help in understanding the better functions.//It uses 24 arithmetic operations (shift, add, and).int popcount_1(uint64 x) {x = (x &amp; m1 ) + ((x » 1) &amp; m1 ); //put count of each 2 bits into those 2 bitsx = (x &amp; m2 ) + ((x » 2) &amp; m2 ); //put count of each 4 bits into those 4 bitsx = (x &amp; m4 ) + ((x » 4) &amp; m4 ); //put count of each 8 bits into those 8 bitsx = (x &amp; m8 ) + ((x » 8) &amp; m8 ); //put count of each 16 bits into those 16 bitsx = (x &amp; m16) + ((x » 16) &amp; m16); //put count of each 32 bits into those 32 bitsx = (x &amp; m32) + ((x » 32) &amp; m32); //put count of each 64 bits into those 64 bitsreturn x;//This uses fewer arithmetic operations than any other known//implementation on machines with slow multiplication.//It uses 17 arithmetic operations.int popcount_2(uint64 x) {x -= (x » 1) &amp; m1; //put count of each 2 bits into those 2 bitsx = (x &amp; m2) + ((x » 2) &amp; m2); //put count of each 4 bits into those 4 bitsx = (x + (x » 4)) &amp; m4; //put count of each 8 bits into those 8 bitsx += x » 8; //put count of each 16 bits into their lowest 8 bitsx += x » 16; //put count of each 32 bits into their lowest 8 bitsx += x » 32; //put count of each 64 bits into their lowest 8 bitsreturn x &amp;0xff;//This uses fewer arithmetic operations than any other known//implementation on machines with fast multiplication.//It uses 12 arithmetic operations, one of which is a multiply.int popcount_3(uint64 x) {x -= (x » 1) &amp; m1; //put count of each 2 bits into those 2 bitsx = (x &amp; m2) + ((x » 2) &amp; m2); //put count of each 4 bits into those 4 bitsx = (x + (x » 4)) &amp; m4; //put count of each 8 bits into those 8 bitsreturn (x * h01)»56; //returns left 8 bits of x + (x«8) + (x«16) + (x«24) + ...在最壞的情況下，上面的實現是所有已知演算法中表現最好的。但是，如果已知大多數資料位是0的話，那麼還有更快的演算法。這些更快的演算法是基於這樣一種事實即X與X-1相"與"得到的最低位永遠是0。例如：減1操作將最右邊的符號從0變到1，從1變到0，"與"操作將會移除最右端的1。如果最初X有N個1，那麼經過N次這樣的迭代運算，X將減到0。下面的演算法就是根據這個原理實現的。//This is better when most bits in x are 0//It uses 3 arithmetic operations and one comparison/branch per "1" bit in x.int popcount_4(uint64 x) {uint64 count;for (count=0; x; count++)x &amp;= x-1;return count;//This is better if most bits in x are 0.//It uses 2 arithmetic operations and one comparison/branch per "1" bit in x.//It is the same as the previous function, but with the loop unrolled.int popcount_5(uint64 x) {if (x == 0) return 0;f( 1) f( 2) f( 3) f( 4) f( 5) f( 6) f( 7) f( 8)f( 9) f(10) f(11) f(12) f(13) f(14) f(15) f(16)f(17) f(18) f(19) f(20) f(21) f(22) f(23) f(24)f(25) f(26) f(27) f(28) f(29) f(30) f(31) f(32)f(33) f(34) f(35) f(36) f(37) f(38) f(39) f(40)f(41) f(42) f(43) f(44) f(45) f(46) f(47) f(48)f(49) f(50) f(51) f(52) f(53) f(54) f(55) f(56)f(57) f(58) f(59) f(60) f(61) f(62) f(63)return 64;//Use this instead if most bits in x are 1 instead of 0