Как найти вес кода заданного битовой строкой

Рассмотрим,
чем определяется способность блочного
кода обнаруживать и исправлять ошибки,
возникшие при передаче.

Пусть
U
= (U
0,
U
1,
U
2,
…U
n-1)
– двоичная последовательность длиной
n.

Число
единиц

(ненулевых компонент) в этой
последовательности называется
весом
Хемминга

вектора U
и обозначается w(U).

Например,
вес Хемминга вектора U
=
( 1001011
) равен четырем, для вектора U
=
( 1111111
)
величина w(U)
составит 7 и т.д.

Таким
образом, чем больше единиц в двоичной
последовательности, тем больше ее вес
Хемминга.

Далее, пусть U и V будут
двоичными последовательностями длиной
n.

Число разрядов, в которых эти
последовательности различаются,
называется расстоянием Хемминга между
U и V и обозначается
d( U, V).

Например,
если U
=
( 1001011
), а V
= ( 0100011
), то d(
U, V) =
3.

Задав
линейный код, то есть определив все 2k
его кодовых слов, можно вычислить
расстояние между всеми возможными
парами кодовых слов. Минимальное из них
называется минимальным
кодовым расстоянием кода

и обозначается dmin.

Можно
проверить и убедиться, что минимальное
кодовое расстояние для рассматриваемого
нами в примерах (7,4)-кода
равно трем: dmin(7,4)
=
3
.
Для этого нужно записать все кодовые
слова (7,4)-кода
Хемминга (всего 16 слов), вычислить
расстояния между их всеми парами и взять
наименьшее значение. Однако можно
определить dmin
блочного кода и более простым способом.

Доказано,
что расстояние между нулевым кодовым
словом и одним из кодовых слов, входящих
в порождающую матрицу (строки порождающей
матрицы линейного блочного кода сами
являются кодовыми словами, по определению),
равно dmin.
Но расстояние от любого кодового слова
до нулевого равно весу Хемминга этого
слова. Тогда dmin
равно минимальному
весу Хемминга

для
всех строк порождающей матрицы кода
.

Если
при передаче кодового слова по каналу
связи в нем произошла одиночная
ошибка
,
то расстояние Хемминга между переданным
словом U
и принятым вектором r

будет равно единице. Если при этом одно
кодовое слово не перешло в другое (а при
dmin
>
1 и при одиночной ошибке это невозможно),
то ошибка будет
обнаружена

при декодировании.

В
общем случае если блочный код имеет
минимальное расстояние dmin,
то он
может обнаруживать любые сочетания
ошибок при их числе, меньшем или равном
dmin

1
,
поскольку никакое сочетание ошибок при
их числе, меньшем, чем dmin

1,

не может перевести одно кодовое слово
в другое.

Но
ошибки могут иметь кратность и большую,
чем dmin
1
,
и тогда они останутся
необнаруженными
.

При
этом среднюю вероятность необнаруживаемой
ошибки можно определить следующим
образом.

Пусть
вероятность ошибки в канале связи равна
Pош.
Тогда вероятность того, что при передаче
последовательности длины n
в ней произойдет одна ошибка, равна

Р1
= n
Pош

( 1- Рош)n-1,
(1.36)

соответственно,
вероятность l-кратной
ошибки –


Pl
=Cnl
Pошl

( 1- Pош)n-l,
(1.37)

где
Cnl
– число возможных комбинаций из
n
символов кодовой последо-вательности
по l
ошибок.

По
каналу связи передаются кодовые слова
с различными весами Хемминга. Положим,
что ai

— число слов с весом i
в данном коде (всего слов в коде длиной
n


).

А
теперь определим, что такое необнаруживаемая
ошибка
.
Обнаружение ошибки производится путем
вычисления синдрома принятой
последовательности. Если принятая
последовательность не является кодовым
словом ( тогда синдром не равен нулю),
то считается, что ошибка есть. Если же
синдром равен нулю, то полагаем, что
ошибки нет (принятая последовательность
является кодовым словом). Но
тем ли, которое передавалось? Или же в
результате действия ошибок переданное
кодовое слово перешло в другое кодовое
слово данного кода:

r
= U
+ е = V,
(1.38)

то
есть сумма переданного кодового слова
U
и вектора ошибки е
даст новое
кодовое слово V
? В этом случае, естественно, ошибка
обнаружена быть не может.

Но
из определения двоичного линейного
кода следует, что если
сумма кодового слова и некоторого
вектора
е
есть кодовое слово, то вектор
е
также представляет собой кодовое слово
.
Следовательно,
необнаруживаемые ошибки будут возникать
тогда, когда сочетания ошибок будут
образовывать кодовые слова.

Вероятность
того, что вектор е
совпадает с кодовым словом, имеющим вес
i
,

равна

Pi
=
Pошi

(1- Рош)n-i
.
(1.39)

Тогда полная
вероятность возникновения необнаруживаемой
ошибки


.
(1.40)

Пример:
рассматриваемый нами (7,4)-код
содержит по семь кодовых слов с весами
w
= 3
и w
= 4
и одно
кодовое слово с весом w
= 7
, тогда

(1.41)

или,
при Рош
= 10

-3,
Р(Е)
7

10

-9.

Другими
словами, если по каналу передается
информация
со скоростью V
=
1кбит/с и в канале в среднем каждую
секунду

будет происходить искажение одного
символа, то в среднем семь принятых слов
на 109
переданных будут проходить через декодер
без обнаружения ошибки (одна необнаруживаемая
ошибка за 270 часов).

Таким
образом, использование даже такого
простого кода позволяет на несколько
порядков снизить вероятность
необнаруживаемых ошибок.

Теперь
предположим, что линейный блочный код
используется для исправления ошибок.
Чем определяются его возможности по
исправлению?

Рассмотрим
пример, приведенный на рис. 1.9. Пусть U
и V
представляют
пару кодовых слов кода с
кодовым расстоянием
d
,

равным минимальному —
d
min

для

данного
кода.

Рис.
1.9

Предположим,
передано кодовое слово U,
в
канале произошла одиночная
ошибка

и принят вектор а

(не
принадлежащий коду).

Если
декодирование производится оптимальным
способом, то есть по
методу максимального правдоподобия,
то в
качестве оценки
U*
нужно
выбрать ближайшее к
а
кодовое
слово.

Таковым
в данном случае будет U,
следовательно, ошибка будет устранена.

Представим
теперь, что произошло две ошибки и принят
вектор b.

Тогда
при декодировании по максимуму
правдоподобия в
качестве оценки будет выбрано ближайшее
к
b
кодовое слово, и им будет

V.
Произойдет ошибка декодирования.

Продолжив
рассуждения для dmin
=
4, d
min
=
5

и т.д., нетрудно сделать вывод, что ошибки
будут устранены, если их кратность l
не превышает величины

l<
INT (( dmin – 1 )/2) ,

(1.41)

где
INT (X)
— целая часть Х.

Так,
используемый нами в качестве примера
(7,4)-код
имеет dmin
= 3
и,
следовательно, позволяет
исправлять лишь одиночные ошибки:

l
= INT
(( dmin
– 1
)/2)=INT((3-1)/2)=1
.
(1.42)

Таким
образом, возможности
линейных блочных кодов по обнаружению
и исправлению ошибок определяются их
минимальным кодовым расстоянием
.
Чем
больше dmin,
тем большее число ошибок в принятой
последовательности можно исправить.

А
теперь определим вероятность того, что
возникшая в процессе передачи ошибка
не будет все же исправлена при
декодировании.

Пусть,
как и ранее, вероятность ошибки в канале
будет равна Рош.
Ошибки, возникающие в различных позициях
кода, считаем независимыми.

Вероятность
того, что принятый вектор r
будет иметь какие-нибудь (одиночные,
двукратные, трехкратные и т.д.) ошибки,
можно определить как

Рош
= P1
+ P2
+ P3
+… + Pn
,

(1.43)

где
Р1
— вероятность того, что в r
присутствует
одиночная ошибка;

Р2

вероятность того, что ошибка двойная и
т.д.;

Рn
— вероятность того, что все n
символов
искажены.

Определим вероятность ошибок заданной
кратности:

Р1
=
Вер{ошибка
в 1-й позиции ИЛИ ошибка во 2-й позиции
..ИЛИ в n-й позиции}
= = Рош(1-
Рош)n-1
+ Рош(1-
Рош)n-1
+…Рош(1-
Рош)n-1
= п 
Рош(1-
Рош)n-;
(1.44)

Р2
=
Вер{ошибка
в 1-й И во 2-й позиции ИЛИ ошибка во 2-й И
в 3-й позиции}
=

=
P2ош(1-Рош)n-2
+…Р2ош(1-
Рош)
n-2
=

Р2ош(1-
Рош)
n-2
.

(1.45)

Аналогичным
образом

Р3
=

Р3ош(1-
Рош)n-3

и т.д.
(1.46)

Декодер,
как мы показали, исправляет все ошибки,
кратность которых не превышает


,
(1.47)

то
есть все ошибки кратности J

l
будут
исправлены.

Тогда
ошибки декодирования – это ошибки с
кратностью, большей кратности исправляемых
ошибок l,

и их вероятность


.
(1.48)

Для
(7,4)-кода
Хемминга минимальное расстояние dmin
=
3
,
т.е. l
=
1.
Следовательно, ошибки кратности 2 и
более исправлены не будут и


.
(1.49)

Если
Рош<<
1,
можно считать (1-
Р
ош)

1
и, кроме того, Р3ош<<
Р
2ош.
Тогда


.
(1.50)

Так, например,
при вероятности ошибки в канале Рош
= 10
-3 вероятность
неисправления ошибки Р(N)
2
10
-5, то есть при такой
вероятности ошибок в канале кодирование
(7.4)-кодом позволяет снизить
вероятность оставшихся неисправленными
ошибок примерно в пятьдесят раз.

Если
же вероятность ошибки в канале будет
в сто раз меньше Рош
= 10
-5, то вероятность
ее неисправления составит уже Р(N)

2
10
-9, или в 5000 раз
меньше
!

Таким
образом, выигрыш от помехоустойчивого
кодирования (который можно определить
как отношение числа ошибок в канале к
числу оставшихся неисправленными
ошибок) существенно зависит от свойств
канала связи.

Если
вероятность ошибок в канале велика, то
есть канал не очень хороший, ожидать
большого эффекта от кодирования не
приходится, если же вероятность ошибок
в канале мала, то корректирующее
кодирование уменьшает ее в значительно
большей степени.

Другими
словами, помехоустойчивое кодирование
существенно улучшает свойства хороших
каналов, в плохих же каналах оно большого
эффекта не дает.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #

    10.06.2015684.82 Кб14P4.pdf

  • #
  • #
  • #
  • #

From Wikipedia, the free encyclopedia

The Hamming weight of a string is the number of symbols that are different from the zero-symbol of the alphabet used. It is thus equivalent to the Hamming distance from the all-zero string of the same length. For the most typical case, a string of bits, this is the number of 1’s in the string, or the digit sum of the binary representation of a given number and the ₁ norm of a bit vector. In this binary case, it is also called the population count,[1] popcount, sideways sum,[2] or bit summation.[3]

Examples

String Hamming weight
11101 4
11101000 4
00000000 0
678012340567 10
A plot for the population count (Hamming weight for binary numbers) for (decimal) numbers 0 to 256.[4][5][6]

History and usage[edit]

The Hamming weight is named after Richard Hamming although he did not originate the notion.[7] The Hamming weight of binary numbers was already used in 1899 by James W. L. Glaisher to give a formula for the number of odd binomial coefficients in a single row of Pascal’s triangle.[8] Irving S. Reed introduced a concept, equivalent to Hamming weight in the binary case, in 1954.[9]

Hamming weight is used in several disciplines including information theory, coding theory, and cryptography. Examples of applications of the Hamming weight include:

  • In modular exponentiation by squaring, the number of modular multiplications required for an exponent e is log2 e + weight(e). This is the reason that the public key value e used in RSA is typically chosen to be a number of low Hamming weight.[10]
  • The Hamming weight determines path lengths between nodes in Chord distributed hash tables.[11]
  • IrisCode lookups in biometric databases are typically implemented by calculating the Hamming distance to each stored record.
  • In computer chess programs using a bitboard representation, the Hamming weight of a bitboard gives the number of pieces of a given type remaining in the game, or the number of squares of the board controlled by one player’s pieces, and is therefore an important contributing term to the value of a position.
  • Hamming weight can be used to efficiently compute find first set using the identity ffs(x) = pop(x ^ (x – 1)). This is useful on platforms such as SPARC that have hardware Hamming weight instructions but no hardware find first set instruction.[12][1]
  • The Hamming weight operation can be interpreted as a conversion from the unary numeral system to binary numbers.[13]
  • In implementation of some succinct data structures like bit vectors and wavelet trees.

Efficient implementation[edit]

The population count of a bitstring is often needed in cryptography and other applications. The Hamming distance of two words A and B can be calculated as the Hamming weight of A xor B.[1]

The problem of how to implement it efficiently has been widely studied. A single operation for the calculation, or parallel operations on bit vectors are available on some processors. For processors lacking those features, the best solutions known are based on adding counts in a tree pattern. For example, to count the number of 1 bits in the 16-bit binary number a = 0110 1100 1011 1010, these operations can be done:

Expression Binary Decimal Comment
a 01 10 11 00 10 11 10 10 27834 The original number
b0 = (a >> 0) & 01 01 01 01 01 01 01 01 01 00 01 00 00 01 00 00 1, 0, 1, 0, 0, 1, 0, 0 Every other bit from a
b1 = (a >> 1) & 01 01 01 01 01 01 01 01 00 01 01 00 01 01 01 01 0, 1, 1, 0, 1, 1, 1, 1 The remaining bits from a
c = b0 + b1 01 01 10 00 01 10 01 01 1, 1, 2, 0, 1, 2, 1, 1 Count of 1s in each 2-bit slice of a
d0 = (c >> 0) & 0011 0011 0011 0011 0001 0000 0010 0001 1, 0, 2, 1 Every other count from c
d2 = (c >> 2) & 0011 0011 0011 0011 0001 0010 0001 0001 1, 2, 1, 1 The remaining counts from c
e = d0 + d2 0010 0010 0011 0010 2, 2, 3, 2 Count of 1s in each 4-bit slice of a
f0 = (e >> 0) & 00001111 00001111 00000010 00000010 2, 2 Every other count from e
f4 = (e >> 4) & 00001111 00001111 00000010 00000011 2, 3 The remaining counts from e
g = f0 + f4 00000100 00000101 4, 5 Count of 1s in each 8-bit slice of a
h0 = (g >> 0) & 0000000011111111 0000000000000101 5 Every other count from g
h8 = (g >> 8) & 0000000011111111 0000000000000100 4 The remaining counts from g
i = h0 + h8 0000000000001001 9 Count of 1s in entire 16-bit word

Here, the operations are as in C programming language, so X >> Y means to shift X right by Y bits, X & Y means the bitwise AND of X and Y, and + is ordinary addition. The best algorithms known for this problem are based on the concept illustrated above and are given here:[1]

//types and constants used in the functions below
//uint64_t is an unsigned 64-bit integer variable type (defined in C99 version of C language)
const uint64_t m1  = 0x5555555555555555; //binary: 0101...
const uint64_t m2  = 0x3333333333333333; //binary: 00110011..
const uint64_t m4  = 0x0f0f0f0f0f0f0f0f; //binary:  4 zeros,  4 ones ...
const uint64_t m8  = 0x00ff00ff00ff00ff; //binary:  8 zeros,  8 ones ...
const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...
const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones
const uint64_t 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.
//This algorithm uses 24 arithmetic operations (shift, add, and).
int popcount64a(uint64_t x)
{
    x = (x & m1 ) + ((x >>  1) & m1 ); //put count of each  2 bits into those  2 bits 
    x = (x & m2 ) + ((x >>  2) & m2 ); //put count of each  4 bits into those  4 bits 
    x = (x & m4 ) + ((x >>  4) & m4 ); //put count of each  8 bits into those  8 bits 
    x = (x & m8 ) + ((x >>  8) & m8 ); //put count of each 16 bits into those 16 bits 
    x = (x & m16) + ((x >> 16) & m16); //put count of each 32 bits into those 32 bits 
    x = (x & m32) + ((x >> 32) & m32); //put count of each 64 bits into those 64 bits 
    return x;
}

//This uses fewer arithmetic operations than any other known  
//implementation on machines with slow multiplication.
//This algorithm uses 17 arithmetic operations.
int popcount64b(uint64_t x)
{
    x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
    x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 
    x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits 
    x += x >>  8;  //put count of each 16 bits into their lowest 8 bits
    x += x >> 16;  //put count of each 32 bits into their lowest 8 bits
    x += x >> 32;  //put count of each 64 bits into their lowest 8 bits
    return x & 0x7f;
}

//This uses fewer arithmetic operations than any other known  
//implementation on machines with fast multiplication.
//This algorithm uses 12 arithmetic operations, one of which is a multiply.
int popcount64c(uint64_t x)
{
    x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
    x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 
    x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits 
    return (x * h01) >> 56;  //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... 
}

The above implementations have the best worst-case behavior of any known algorithm. However, when a value is expected to have few nonzero bits, it may instead be more efficient to use algorithms that count these bits one at a time. As Wegner described in 1960,[14] the bitwise AND of x with x − 1 differs from x only in zeroing out the least significant nonzero bit: subtracting 1 changes the rightmost string of 0s to 1s, and changes the rightmost 1 to a 0. If x originally had n bits that were 1, then after only n iterations of this operation, x will be reduced to zero. The following implementation is based on this principle.

//This is better when most bits in x are 0
//This algorithm works the same for all data sizes.
//This algorithm uses 3 arithmetic operations and 1 comparison/branch per "1" bit in x.
int popcount64d(uint64_t x)
{
    int count;
    for (count=0; x; count++)
        x &= x - 1;
    return count;
}

If greater memory usage is allowed, we can calculate the Hamming weight faster than the above methods. With unlimited memory, we could simply create a large lookup table of the Hamming weight of every 64 bit integer. If we can store a lookup table of the hamming function of every 16 bit integer, we can do the following to compute the Hamming weight of every 32 bit integer.

static uint8_t wordbits[65536] = { /* bitcounts of integers 0 through 65535, inclusive */ };
//This algorithm uses 3 arithmetic operations and 2 memory reads.
int popcount32e(uint32_t x)
{
    return wordbits[x & 0xFFFF] + wordbits[x >> 16];
}
//Optionally, the wordbits[] table could be filled using this function
int popcount32e_init(void)
{
    uint32_t i;
    uint16_t x;
    int count;
    for (i=0; i <= 0xFFFF; i++)
    {
        x = i;
        for (count=0; x; count++) // borrowed from popcount64d() above
            x &= x - 1;
        wordbits[i] = count;
    }
}

Muła et al.[15] have shown that a vectorized version of popcount64b can run faster than dedicated instructions (e.g., popcnt on x64 processors).

Minimum weight[edit]

In error-correcting coding, the minimum Hamming weight, commonly referred to as the minimum weight wmin of a code is the weight of the lowest-weight non-zero code word. The weight w of a code word is the number of 1s in the word. For example, the word 11001010 has a weight of 4.

In a linear block code the minimum weight is also the minimum Hamming distance (dmin) and defines the error correction capability of the code. If wmin = n, then dmin = n and the code will correct up to dmin/2 errors.[16]

Language support[edit]

Some C compilers provide intrinsic functions that provide bit counting facilities. For example, GCC (since version 3.4 in April 2004) includes a builtin function __builtin_popcount that will use a processor instruction if available or an efficient library implementation otherwise.[17] LLVM-GCC has included this function since version 1.5 in June 2005.[18]

In the C++ Standard Library, the bit-array data structure bitset has a count() method that counts the number of bits that are set. In C++20, a new header <bit> was added, containing functions std::popcount and std::has_single_bit, taking arguments of unsigned integer types.

In Java, the growable bit-array data structure BitSet has a BitSet.cardinality() method that counts the number of bits that are set. In addition, there are Integer.bitCount(int) and Long.bitCount(long) functions to count bits in primitive 32-bit and 64-bit integers, respectively. Also, the BigInteger arbitrary-precision integer class also has a BigInteger.bitCount() method that counts bits.

In Python, the int type has a bit_count() method to count the number of bits set. This functionality was introduced in Python 3.10, released in October 2021.[19]

In Common Lisp, the function logcount, given a non-negative integer, returns the number of 1 bits. (For negative integers it returns the number of 0 bits in 2’s complement notation.) In either case the integer can be a BIGNUM.

Starting in GHC 7.4, the Haskell base package has a popCount function available on all types that are instances of the Bits class (available from the Data.Bits module).[20]

MySQL version of SQL language provides BIT_COUNT() as a standard function.[21]

Fortran 2008 has the standard, intrinsic, elemental function popcnt returning the number of nonzero bits within an integer (or integer array).[22]

Some programmable scientific pocket calculators feature special commands to calculate the number of set bits, e.g. #B on the HP-16C[3][23] and WP 43S,[24][25] #BITS[26][27] or BITSUM[28][29] on HP-16C emulators, and nBITS on the WP 34S.[30][31]

FreePascal implements popcnt since version 3.0.[32]

Processor support[edit]

  • The IBM STRETCH computer in the 1960s calculated the number of set bits as well as the number of leading zeros as a by-product of all logical operations.[1]
  • Cray supercomputers early on featured a population count machine instruction, rumoured to have been specifically requested by the U.S. government National Security Agency for cryptanalysis applications.[1]
  • Control Data Corporation’s (CDC) 6000 and Cyber 70/170 series machines included a population count instruction; in COMPASS, this instruction was coded as CXi.
  • The 64-bit SPARC version 9 architecture defines a POPC instruction,[12][1] but most implementations do not implement it, requiring it be emulated by the operating system.[33]
  • Donald Knuth’s model computer MMIX that is going to replace MIX in his book The Art of Computer Programming has an SADD instruction since 1999. SADD a,b,c counts all bits that are 1 in b and 0 in c and writes the result to a.
  • Compaq’s Alpha 21264A, released in 1999, was the first Alpha series CPU design that had the count extension (CIX).
  • Analog Devices’ Blackfin processors feature the ONES instruction to perform a 32-bit population count.[34]
  • AMD’s Barcelona architecture introduced the advanced bit manipulation (ABM) ISA introducing the POPCNT instruction as part of the SSE4a extensions in 2007.
  • Intel Core processors introduced a POPCNT instruction with the SSE4.2 instruction set extension, first available in a Nehalem-based Core i7 processor, released in November 2008.
  • The ARM architecture introduced the VCNT instruction as part of the Advanced SIMD (NEON) extensions.
  • The RISC-V architecture introduced the PCNT instruction as part of the Bit Manipulation (B) extension.[35]

See also[edit]

  • Two’s complement
  • Fan out

References[edit]

  1. ^ a b c d e f g Warren Jr., Henry S. (2013) [2002]. Hacker’s Delight (2 ed.). Addison Wesley – Pearson Education, Inc. pp. 81–96. ISBN 978-0-321-84268-8. 0-321-84268-5.
  2. ^ Knuth, Donald Ervin (2009). “Bitwise tricks & techniques; Binary Decision Diagrams”. The Art of Computer Programming. Vol. 4, Fascicle 1. Addison–Wesley Professional. ISBN 978-0-321-58050-4. (NB. Draft of Fascicle 1b available for download.)
  3. ^ a b Hewlett-Packard HP-16C Computer Scientist Owner’s Handbook (PDF). Hewlett-Packard Company. April 1982. 00016-90001. Archived (PDF) from the original on 2017-03-28. Retrieved 2017-03-28.
  4. ^ [1], written in Fōrmulæ. The Fōrmulæ wiki. Retrieved 2019-09-30.
  5. ^ A solution to the task Population count. Retrieved 2019-09-30.
  6. ^ Rosetta Code. Retrieved 2019-09-30.
  7. ^ Thompson, Thomas M. (1983). From Error-Correcting Codes through Sphere Packings to Simple Groups. The Carus Mathematical Monographs #21. The Mathematical Association of America. p. 33.
  8. ^ Glaisher, James Whitbread Lee (1899). “On the residue of a binomial-theorem coefficient with respect to a prime modulus”. The Quarterly Journal of Pure and Applied Mathematics. 30: 150–156. (NB. See in particular the final paragraph of p. 156.)
  9. ^ Reed, Irving Stoy (1954). “A Class of Multiple-Error-Correcting Codes and the Decoding Scheme”. IRE Professional Group on Information Theory. Institute of Radio Engineers (IRE). PGIT-4: 38–49.
  10. ^ Cohen, Gérard D.; Lobstein, Antoine; Naccache, David; Zémor, Gilles (1998). “How to improve an exponentiation black-box”. In Nyberg, Kaisa (ed.). Advances in Cryptology – EUROCRYPT ’98, International Conference on the Theory and Application of Cryptographic Techniques, Espoo, Finland, May 31 – June 4, 1998, Proceeding. Lecture Notes in Computer Science. Vol. 1403. Springer. pp. 211–220. doi:10.1007/BFb0054128.
  11. ^ Stoica, I.; Morris, R.; Liben-Nowell, D.; Karger, D. R.; Kaashoek, M. F.; Dabek, F.; Balakrishnan, H. (February 2003). “Chord: a scalable peer-to-peer lookup protocol for internet applications”. IEEE/ACM Transactions on Networking. 11 (1): 17–32. doi:10.1109/TNET.2002.808407. S2CID 221276912. Section 6.3: “In general, the number of fingers we need to follow will be the number of ones in the binary representation of the distance from node to query.”
  12. ^ a b SPARC International, Inc. (1992). “A.41: Population Count. Programming Note”. The SPARC architecture manual: version 8 (Version 8 ed.). Englewood Cliffs, New Jersey, USA: Prentice Hall. pp. 231. ISBN 0-13-825001-4.
  13. ^ Blaxell, David (1978). Hogben, David; Fife, Dennis W. (eds.). “Record linkage by bit pattern matching”. Computer Science and Statistics–Tenth Annual Symposium on the Interface. NBS Special Publication. U.S. Department of Commerce / National Bureau of Standards. 503: 146–156.
  14. ^ Wegner, Peter (May 1960). “A technique for counting ones in a binary computer”. Communications of the ACM. 3 (5): 322. doi:10.1145/367236.367286. S2CID 31683715.
  15. ^ Muła, Wojciech; Kurz, Nathan; Lemire, Daniel (January 2018). “Faster Population Counts Using AVX2 Instructions”. Computer Journal. 61 (1): 111–120. arXiv:1611.07612. doi:10.1093/comjnl/bxx046. S2CID 540973.
  16. ^ Stern & Mahmoud, Communications System Design, Prentice Hall, 2004, p 477ff.
  17. ^ “GCC 3.4 Release Notes”. GNU Project.
  18. ^ “LLVM 1.5 Release Notes”. LLVM Project.
  19. ^ “What’s New In Python 3.10”. python.org.
  20. ^ “GHC 7.4.1 release notes”. GHC documentation.
  21. ^ “Chapter 12.11. Bit Functions — MySQL 5.0 Reference Manual”.
  22. ^ Metcalf, Michael; Reid, John; Cohen, Malcolm (2011). Modern Fortran Explained. Oxford University Press. p. 380. ISBN 978-0-19-960142-4.
  23. ^ Schwartz, Jake; Grevelle, Rick (2003-10-20) [1993]. HP16C Emulator Library for the HP48S/SX. 1.20 (1 ed.). Retrieved 2015-08-15. (NB. This library also works on the HP 48G/GX/G+. Beyond the feature set of the HP-16C this package also supports calculations for binary, octal, and hexadecimal floating-point numbers in scientific notation in addition to the usual decimal floating-point numbers.)
  24. ^ Bonin, Walter (2019) [2015]. WP 43S Owner’s Manual (PDF). 0.12 (draft ed.). p. 135. ISBN 978-1-72950098-9. Retrieved 2019-08-05. [2] [3] (314 pages)
  25. ^ Bonin, Walter (2019) [2015]. WP 43S Reference Manual (PDF). 0.12 (draft ed.). pp. xiii, 104, 115, 120, 188. ISBN 978-1-72950106-1. Retrieved 2019-08-05. [4] [5] (271 pages)
  26. ^ Martin, Ángel M.; McClure, Greg J. (2015-09-05). “HP16C Emulator Module for the HP-41CX – User’s Manual and QRG” (PDF). Archived (PDF) from the original on 2017-04-27. Retrieved 2017-04-27. (NB. Beyond the HP-16C feature set this custom library for the HP-41CX extends the functionality of the calculator by about 50 additional functions.)
  27. ^ Martin, Ángel M. (2015-09-07). “HP-41: New HP-16C Emulator available”. Archived from the original on 2017-04-27. Retrieved 2017-04-27.
  28. ^ Thörngren, Håkan (2017-01-10). “Ladybug Documentation” (release 0A ed.). Retrieved 2017-01-29. [6]
  29. ^ “New HP-41 module available: Ladybug”. 2017-01-10. Archived from the original on 2017-01-29. Retrieved 2017-01-29.
  30. ^ Dale, Paul; Bonin, Walter (2012) [2008]. “WP 34S Owner’s Manual” (PDF) (3.1 ed.). Retrieved 2017-04-27.
  31. ^ Bonin, Walter (2015) [2008]. WP 34S Owner’s Manual (3.3 ed.). ISBN 978-1-5078-9107-0.
  32. ^ “Free Pascal documentation popcnt”. Retrieved 2019-12-07.
  33. ^ “JDK-6378821: bitCount() should use POPC on SPARC processors and AMD+10h”. Java bug database. 2006-01-30.
  34. ^ Blackfin Instruction Set Reference (Preliminary ed.). Analog Devices. 2001. pp. 8–24. Part Number 82-000410-14.
  35. ^ Wolf, Claire (2019-03-22). “RISC-V “B” Bit Manipulation Extension for RISC-V, Draft v0.37″ (PDF). Github.

Further reading[edit]

  • Schroeppel, Richard C.; Orman, Hilarie K. (1972-02-29). “compilation”. HAKMEM. By Beeler, Michael; Gosper, Ralph William; Schroeppel, Richard C. (report). Artificial Intelligence Laboratory, Massachusetts Institute of Technology, Cambridge, Massachusetts, USA. MIT AI Memo 239. (Item 169: Population count assembly code for the PDP/6-10.)

External links[edit]

  • Aggregate Magic Algorithms. Optimized population count and other algorithms explained with sample code.
  • Bit Twiddling Hacks Several algorithms with code for counting bits set.
  • Necessary and Sufficient – by Damien Wintour – Has code in C# for various Hamming Weight implementations.
  • Best algorithm to count the number of set bits in a 32-bit integer? – Stackoverflow

Вес Хэмминга из строки есть число символов, отличные от нулевого символа алфавита , используемым. Таким образом, это эквивалентно расстоянию Хэмминга от нулевой строки той же длины. Для наиболее типичного случая, строк биты , это число 1 – й в строке, или цифра сумма в двоичном представлении заданного числа и л ₁ нормы битового вектора. В этом двоичном случае, он также называется количество населения , popcount , вбок сумма , или битовое суммирование .

Примеры

Нить Вес Хэмминга
111 0 1 4
111 0 1 000 4
00000000 0
678 0 1234 0 567 10
График подсчета населения (вес Хэмминга для двоичных чисел) для (десятичных) чисел от 0 до 256.

История и использование

Гиря Хэмминга названа в честь Ричарда Хэмминга, хотя это понятие не принадлежит ему. Вес Хэмминга двоичных чисел уже использовался в 1899 году Джеймсом В.Л. Глейшером, чтобы дать формулу для количества нечетных биномиальных коэффициентов в одной строке треугольника Паскаля . Ирвинг С. Рид ввел понятие, эквивалентное весу Хэмминга в двоичном случае, в 1954 году.

Хэмминга вес используется в нескольких областях , включая теорию информации , теории кодирования и криптографии . Примеры применения веса Хэмминга:

  • При модульном возведении в степень возведением в квадрат количество модульных умножений, необходимых для экспоненты e, равно log 2 e + weight ( e ). Это причина того, что значение открытого ключа e, используемое в RSA , обычно выбирается как число с низким весом Хэмминга.
  • Вес Хэмминга определяет длину пути между узлами в распределенных хэш-таблицах Chord .
  • Поиск IrisCode в биометрических базах данных обычно осуществляется путем вычисления расстояния Хэмминга до каждой сохраненной записи.
  • В компьютерных шахматных программах, использующих представление битовой доски , вес Хэмминга битовой доски дает количество фигур данного типа, оставшихся в игре, или количество квадратов доски, контролируемых фигурами одного игрока, и, следовательно, является важным вспомогательным термином. к стоимости позиции.
  • Вес Хэмминга можно использовать для эффективного вычисления первого набора с использованием тождества ffs (x) = pop (x ^ (x – 1)). Это полезно на таких платформах, как SPARC , у которых есть аппаратные инструкции веса Хэмминга, но нет аппаратных инструкций по поиску первого набора.
  • Операцию веса Хэмминга можно интерпретировать как преобразование из унарной системы счисления в двоичные числа .
  • В реализации некоторых лаконичных структур данных, таких как битовые векторы и вейвлет-деревья .

Эффективное внедрение

Подсчет заполнения строки битов часто требуется в криптографии и других приложениях. Расстояние Хэмминга двух слов A и B могут быть рассчитаны как вес Хэмминга A исключающего B .

Проблема того, как его эффективно реализовать, широко изучается. На некоторых процессорах доступны одиночные операции для вычисления или параллельные операции с битовыми векторами . Для процессоров, не имеющих этих функций, лучшие известные решения основаны на добавлении счетчиков в древовидной структуре. Например, чтобы подсчитать количество 1 бит в 16-битном двоичном числе a = 0110 1100 1011 1010, можно выполнить следующие операции:

Выражение Двоичный Десятичная дробь Комментарий
a 01 10 11 00 10 11 10 10 27834 Исходный номер
b0 = (a >> 0) & 01 01 01 01 01 01 01 01 01 00 01 00 00 01 00 00 1, 0, 1, 0, 0, 1, 0, 0 Каждый другой бит от
b1 = (a >> 1) & 01 01 01 01 01 01 01 01 00 01 01 00 01 01 01 01 0, 1, 1, 0, 1, 1, 1, 1 Остальные биты из
c = b0 + b1 01 01 10 00 01 10 01 01 1, 1, 2, 0, 1, 2, 1, 1 Подсчет единиц в каждом 2-битном срезе
d0 = (c >> 0) & 0011 0011 0011 0011 0001 0000 0010 0001 1, 0, 2, 1 Все остальные отсчитываются от c
d2 = (c >> 2) & 0011 0011 0011 0011 0001 0010 0001 0001 1, 2, 1, 1 Остальные отсчеты от c
e = d0 + d2 0010 0010 0011 0010 2, 2, 3, 2 Подсчет единиц в каждом 4-битном срезе
f0 = (e >> 0) & 00001111 00001111 00000010 00000010 2, 2 Все остальные считают от е
f4 = (e >> 4) & 00001111 00001111 00000010 00000011 2, 3 Остальные отсчеты от e
g = f0 + f4 00000100 00000101 4, 5 Подсчет единиц в каждом 8-битном срезе
h0 = (g >> 0) & 0000000011111111 0000000000000101 5 Все остальные считают от g
h8 = (g >> 8) & 0000000011111111 0000000000000100 4 Остальные отсчеты от g
i = h0 + h8 0000000000001001 9 Подсчет единиц во всем 16-битном слове

Здесь операции такие же, как в языке программирования C , поэтому X >> Yозначает сдвиг X вправо на биты Y, X & Y означает побитовое И для X и Y, а + – обычное сложение. Лучшие алгоритмы, известные для этой проблемы, основаны на концепции, проиллюстрированной выше, и приведены здесь:

//types and constants used in the functions below
//uint64_t is an unsigned 64-bit integer variable type (defined in C99 version of C language)
const uint64_t m1  = 0x5555555555555555; //binary: 0101...
const uint64_t m2  = 0x3333333333333333; //binary: 00110011..
const uint64_t m4  = 0x0f0f0f0f0f0f0f0f; //binary:  4 zeros,  4 ones ...
const uint64_t m8  = 0x00ff00ff00ff00ff; //binary:  8 zeros,  8 ones ...
const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...
const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones
const uint64_t 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.
//This algorithm uses 24 arithmetic operations (shift, add, and).
int popcount64a(uint64_t x)
{
    x = (x & m1 ) + ((x >>  1) & m1 ); //put count of each  2 bits into those  2 bits 
    x = (x & m2 ) + ((x >>  2) & m2 ); //put count of each  4 bits into those  4 bits 
    x = (x & m4 ) + ((x >>  4) & m4 ); //put count of each  8 bits into those  8 bits 
    x = (x & m8 ) + ((x >>  8) & m8 ); //put count of each 16 bits into those 16 bits 
    x = (x & m16) + ((x >> 16) & m16); //put count of each 32 bits into those 32 bits 
    x = (x & m32) + ((x >> 32) & m32); //put count of each 64 bits into those 64 bits 
    return x;
}

//This uses fewer arithmetic operations than any other known  
//implementation on machines with slow multiplication.
//This algorithm uses 17 arithmetic operations.
int popcount64b(uint64_t x)
{
    x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
    x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 
    x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits 
    x += x >>  8;  //put count of each 16 bits into their lowest 8 bits
    x += x >> 16;  //put count of each 32 bits into their lowest 8 bits
    x += x >> 32;  //put count of each 64 bits into their lowest 8 bits
    return x & 0x7f;
}

//This uses fewer arithmetic operations than any other known  
//implementation on machines with fast multiplication.
//This algorithm uses 12 arithmetic operations, one of which is a multiply.
int popcount64c(uint64_t x)
{
    x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
    x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 
    x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits 
    return (x * h01) >> 56;  //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... 
}

Вышеупомянутые реализации обладают наилучшим поведением в худшем случае из всех известных алгоритмов. Однако, когда ожидается, что значение будет иметь несколько ненулевых битов, вместо этого может быть более эффективным использовать алгоритмы, которые подсчитывают эти биты по одному. Как описал Вегнер в 1960 году, побитовое И для x с x  – 1 отличается от x только обнулением наименее значимого ненулевого бита: вычитание 1 изменяет крайнюю правую строку из 0 на 1 и заменяет крайнюю правую 1 на 0. Если x изначально было n битов, равных 1, затем после n итераций этой операции x будет уменьшено до нуля. Следующая реализация основана на этом принципе.

//This is better when most bits in x are 0
//This algorithm works the same for all data sizes.
//This algorithm uses 3 arithmetic operations and 1 comparison/branch per "1" bit in x.
int popcount64d(uint64_t x)
{
    int count;
    for (count=0; x; count++)
        x &= x - 1;
    return count;
}

Если разрешено большее использование памяти, мы можем вычислить вес Хэмминга быстрее, чем описанные выше методы. Имея неограниченную память, мы могли бы просто создать большую таблицу поиска веса Хэмминга для каждого 64-битного целого числа. Если мы можем сохранить таблицу поиска функции Хэмминга для каждого 16-битного целого числа, мы можем сделать следующее, чтобы вычислить вес Хэмминга для каждого 32-битного целого числа.

static uint8_t wordbits[65536] = { /* bitcounts of integers 0 through 65535, inclusive */ };
//This algorithm uses 3 arithmetic operations and 2 memory reads.
int popcount32e(uint32_t x)
{
    return wordbits[x & 0xFFFF] + wordbits[x >> 16];
}
//Optionally, the wordbits[] table could be filled using this function
int popcount32e_init(void)
{
    uint32_t i;
    uint16_t x;
    int count;
    for (i=0; i <= 0xFFFF; i++)
    {
        x = i;
        for (count=0; x; count++) // borrowed from popcount64d() above
            x &= x - 1;
        wordbits[i] = count;
    }
}

Muła et al. показали, что векторизованная версия popcount64b может работать быстрее, чем специальные инструкции (например, popcnt на процессорах x64).

Минимальный вес

При кодировании с исправлением ошибок минимальный вес Хэмминга, обычно называемый минимальным весом w min кода, представляет собой вес ненулевого кодового слова с наименьшим весом. Вес w кодового слова – это количество единиц в слове. Например, слово 11001010 имеет вес 4.

В линейном блочном коде минимальный вес также является минимальным расстоянием Хэмминга ( d min ) и определяет способность кода исправлять ошибки. Если w min  =  n , то d min  =  n, и код исправит до d min / 2 ошибок.

Языковая поддержка

Некоторые компиляторы C предоставляют встроенные функции, обеспечивающие подсчет битов. Например, GCC (начиная с версии 3.4 в апреле 2004 г.) включает встроенную функцию, __builtin_popcountкоторая будет использовать инструкцию процессора, если она доступна, или эффективную реализацию библиотеки в противном случае. LLVM-GCC включает эту функцию с версии 1.5 в июне 2005 года.

В C ++ STL структура данных битового массива bitsetимеет count()метод, который подсчитывает количество установленных битов. В C ++ 20<bit> был добавлен новый заголовок , содержащий функции std::popcountи std::has_single_bit, принимающий аргументы целочисленных типов без знака.

В Java структура данных растущего битового массива BitSetимеет BitSet.cardinality()метод, который подсчитывает количество установленных битов. Кроме того, существует Integer.bitCount(int)и Long.bitCount(long)функция для подсчета бит в примитивных 32-битных и 64-битных числах, соответственно. Кроме того, BigIntegerцелочисленный класс произвольной точности также имеет BigInteger.bitCount()метод подсчета битов.

В Python у этого intтипа есть bit_count()метод для подсчета количества установленных битов. Эта функция является новой в Python 3.10, выпуск которой запланирован на 2021 год.

В Common Lisp функция logcount, учитывая неотрицательное целое число, возвращает количество битов, равное единице. (Для отрицательных целых чисел он возвращает количество 0 бит в нотации дополнения до 2.) В любом случае целое число может быть BIGNUM.

Начиная с GHC 7.4, в базовом пакете Haskell есть popCountфункция, доступная для всех типов, которые являются экземплярами Bitsкласса (доступны из Data.Bitsмодуля).

MySQL версии SQL языка обеспечивает в BIT_COUNT()качестве стандартной функции.

Fortran 2008 имеет стандартную внутреннюю элементарную функцию, popcntвозвращающую количество ненулевых битов в целочисленном (или целочисленном массиве).

Некоторые программируемые карманные калькуляторы для научных исследований имеют специальные команды для вычисления количества установленных битов, например, #Bна HP-16C и WP 43S , #BITSили BITSUMна эмуляторах HP-16C, и nBITSна WP 34S .

FreePascal реализует popcnt начиная с версии 3.0.

Поддержка процессора

  • IBM STRETCH компьютер в 1960 – х годах подсчитан число установленных бит, а также ряд ведущих нулей в качестве побочного продукта всех логических операций.
  • Вначале суперкомпьютеры Cray имели машинную команду подсчета населения, которая , по слухам, была специально запрошена Агентством национальной безопасности США для приложений криптоанализа .
  • Машины серий Control Data Corporation (CDC) 6000 и Cyber ​​70/170 включали в себя инструкцию по подсчету населения; в КОМПАСЕ эта инструкция была закодирована как CXi.
  • 64-битная архитектура SPARC версии 9 определяет POPCинструкцию, но большинство реализаций ее не реализуют, требуя ее эмуляции операционной системой.
  • Модель MMIX Дональда Кнута, которая заменит MIX в его книге «Искусство компьютерного программирования», имеет SADDинструкцию с 1999 года. SADD a,b,cСчитает все биты, которые равны 1 в b и 0 в c, и записывает результат в a.
  • Compaq «ы Альфа 21264A , выпущенный в 1999 году, был первым альфа дизайн серии процессоров , которые имели расширение счетчика ( CIX).
  • Analog Devices ‘ Blackfin процессоры имеют в ONESинструкции для выполнения 32-битного счетчика населения.
  • Архитектура AMD « Барселона» представила ISA расширенного управления битами (ABM), представив POPCNTинструкцию как часть расширений SSE4a в 2007 году.
  • Intel Core процессоры представили POPCNTинструкцию с SSE4.2 набором команд расширения, первым доступным в Nehalem – Core i7 процессора, выпущенном в ноябре 2008 года.
  • Архитектура ARM представила VCNTинструкцию как часть расширений Advanced SIMD ( NEON ).
  • Архитектура RISC-V представила PCNTинструкцию как часть расширения Bit Manipulation (B).

Смотрите также

  • Два дополнения
  • Наиболее часто встречающиеся символы k
  • Развернуть веер

использованная литература

дальнейшее чтение

  • Schroeppel, Ричард К .; Орман, Хилари К. (1972-02-29). “сборник”. ХАКМЕМ . Билер, Майкл; Госпер, Ральф Уильям ; Schroeppel, Ричард К. (отчет). Лаборатория искусственного интеллекта , Массачусетский технологический институт , Кембридж, Массачусетс, США. Записка Массачусетского технологического института по искусственному интеллекту 239.( Элемент 169 : Сборочный код подсчета населения для PDP / 6-10.)

внешние ссылки

  • Агрегированные магические алгоритмы . Оптимизированный подсчет населения и другие алгоритмы, объясненные в образце кода.
  • Взломы Bit Twiddling Несколько алгоритмов с кодом для подсчета установленных битов.
  • Необходимые и достаточные – Дэмиен Винтур – Имеет код на C # для различных реализаций Веса Хэмминга.
  • Лучший алгоритм для подсчета количества установленных битов в 32-битном целом числе? – Переполнение стека

Код на Ревью

function hammingWeight($weight)
{
    $array = str_split(decbin($weight));
    $amount = 0;
    foreach ($array as $value) {
        $amount += $value;
    }
    return $amount;
}

Контрольные точки

  • Понятно ли с первого взгляда что делает функция (основываясь на содержимом)?
  • Попробуйте воспроизвести определение понятия “Вес Хемминга” глядя только на код

Спецификация

Вес Хэмминга это количество единиц в двоичном представлении числа.
Реализуйте функцию hammingWeight, которая считает вес Хэмминга.

Проблемы

Ничего не говорящие и запутывающие имена переменных

Как известно, именование переменных, является одной из самых сложных задач в разработке и данный пример это подтверждает.
Плохие имена не только не помогают читать код, но и могут запутывать. В данном примере переменная $weight это, на самом деле,
исходное число, а вес это $amount.

Имя $array не запутывает, но и не помогает. Разумно, в данном случае, было назвать переменную $digits, что соответствует сути.

Алгоритм вычисления веса опирается не на спецификацию, а на корреляцию

По случайному совпадению оказалось что можно сложить все цифры, из которых состоит число в двоичном представлении, и мы получим вес Хемминга.
Да это сработает и этим фактом воспользовался автор, но определение веса Хемминга звучит совсем по другому. Это приводит к семантическому
разрыву. По коду сложно понять и восстановить описание, а так же верно и обратное. После знакомства с определением, трудно увидеть в коде
его реализацию.

Алгоритм опирается на особенности типизации в php

PHP обладает, так называемой, слабой типизацией. Это означает что php автоматически преобразует типы операндов в различных операциях,
вместо того чтобы сообщить об ошибке. Например при сложении числа со строкой. Слабая типизация это источник большого количества проблем
и странного поведения программы при определенных входных данных. Это относится не только к php, в javascript ситуация точно такая же.

Вывод

Функция выглядит магической и требует время на осознание. Перед тем как она будет понята, смотрящему придется увидеть указанную корреляцию.

Решение

Использовать реализацию основанную на определении понятия “вес Хемминга”.

function hammingWeight($num)
{
    $weight = 0;
    $digits = str_split(decbin($num));
    foreach ($digits as $value) {
        if ($value == '1') {
            $weight++;
        }
    }
    return $weight;
}

Эта статья нужны дополнительные цитаты для проверка. Пожалуйста помоги улучшить эту статью к добавление цитат в надежные источники. Материал, не полученный от источника, может быть оспорен и удален.
Найдите источники: “Вес Хэмминга”  – Новости  · газеты  · книги  · ученый  · JSTOR
(Январь 2009 г.) (Узнайте, как и когда удалить этот шаблон сообщения)

В Вес Хэмминга из нить – количество символов, отличных от нулевого символа алфавит использовал. Таким образом, это эквивалентно Расстояние Хэмминга из нулевой строки той же длины. В наиболее типичном случае строка биты, это количество единиц в строке или цифра сумма из двоичное представление заданного числа и ₁ норма битового вектора. В этом двоичном случае он также называется подсчет населения,[1] popcount, боковая сумма,[2] или же битовое суммирование.[3]

Примеры

Нить Вес Хэмминга
11101 4
11101000 4
00000000 0
678012340567 10

График подсчета населения (вес Хэмминга для двоичных чисел) для (десятичных) чисел от 0 до 256.[4][5][6]

История и использование

Вес Хэмминга назван в честь Ричард Хэмминг хотя это понятие не принадлежит ему.[7] Вес Хэмминга двоичных чисел уже использовался в 1899 г. Джеймс В. Л. Глейшер дать формулу для количество нечетных биномиальных коэффициентов в один ряд Треугольник Паскаля.[8] Ирвинг С. Рид ввел понятие, эквивалентное весу Хэмминга в двоичном случае, в 1954 г.[9]

Вес Хэмминга используется в нескольких дисциплинах, включая теория информации, теория кодирования, и криптография. Примеры применения веса Хэмминга:

  • В модульном возведение в степень возведением в квадрат, количество модульных умножений, необходимых для экспоненты е журнал2 е + вес (е). Это причина того, что значение открытого ключа е используется в ЮАР обычно выбирается число с низким весом Хэмминга.
  • Вес Хэмминга определяет длину пути между узлами в Распределенные хэш-таблицы по аккорду.[10]
  • IrisCode поиск в биометрических базах данных обычно осуществляется путем расчета Расстояние Хэмминга к каждой сохраненной записи.
  • В компьютерные шахматы программы, использующие битовая доска В представлении, вес Хэмминга битовой доски дает количество фишек данного типа, оставшихся в игре, или количество квадратов доски, контролируемых фишками одного игрока, и, следовательно, является важным термином, влияющим на значение позиции.
  • Вес Хэмминга можно использовать для эффективного вычисления найти первый набор используя тождество ffs (x) = pop (x ^ (x-1)). Это полезно на таких платформах, как SPARC у которых есть аппаратные инструкции по весу Хэмминга, но нет аппаратной команды поиска первой установки.[11][1]
  • Весовую операцию Хэмминга можно интерпретировать как преобразование из унарная система счисления к двоичные числа.[12]
  • В реализации некоторых лаконичные структуры данных подобно битовые векторы и вейвлет-деревья.

Эффективное внедрение

Подсчет населения битовая строка часто требуется в криптографии и других приложениях. В Расстояние Хэмминга из двух слов А и B можно рассчитать как вес Хэмминга А xor B.[1]

Проблема того, как его эффективно реализовать, широко изучается. Одна операция для вычисления или параллельные операции над битовыми векторами: доступно на некоторых процессорах. Для процессоров, не имеющих этих функций, лучшие известные решения основаны на добавлении счетчиков в древовидной структуре. Например, чтобы подсчитать количество 1 бит в 16-битном двоичном числе a = 0110 1100 1011 1010, можно выполнить следующие операции:

Выражение Двоичный Десятичный Комментарий
а 01 10 11 00 10 11 10 10 27834 Исходный номер
b0 = (a >> 0) & 01 01 01 01 01 01 01 01 01 00 01 00 00 01 00 00 1, 0, 1, 0, 0, 1, 0, 0 Каждый другой бит из
b1 = (a >> 1) & 01 01 01 01 01 01 01 01 00 01 01 00 01 01 01 01 0, 1, 1, 0, 1, 1, 1, 1 Остальные биты из
с = b0 + b1 01 01 10 00 01 10 01 01 1, 1, 2, 0, 1, 2, 1, 1 Подсчет единиц в каждом 2-битном срезе
d0 = (c >> 0) & 0011 0011 0011 0011 0001 0000 0010 0001 1, 0, 2, 1 Все остальные считают от c
d2 = (c >> 2) & 0011 0011 0011 0011 0001 0010 0001 0001 1, 2, 1, 1 Остальные отсчеты от c
е = d0 + d2 0010 0010 0011 0010 2, 2, 3, 2 Подсчет единиц в каждом 4-битном срезе
f0 = (e >> 0) & 00001111 00001111 00000010 00000010 2, 2 Все остальные считают от е
f4 = (e >> 4) & 00001111 00001111 00000010 00000011 2, 3 Остальные отсчеты от e
г = f0 + f4 00000100 00000101 4, 5 Подсчет единиц в каждом 8-битном срезе
h0 = (g >> 0) & 0000000011111111 0000000000000101 5 Все остальные считают от g
h8 = (g >> 8) & 0000000011111111 0000000000000100 4 Остальные отсчеты от g
я = h0 + h8 0000000000001001 9 Подсчет единиц во всем 16-битном слове

Здесь операции такие же, как в Язык программирования C, так X >> Y означает сдвиг X вправо на биты Y, X & Y означает побитовое И для X и Y, а + – обычное сложение. Лучшие алгоритмы, известные для этой проблемы, основаны на концепции, проиллюстрированной выше, и приведены здесь:[1]

// типы и константы, используемые в функциях ниже// uint64_t - это беззнаковый 64-битный целочисленный тип переменной (определен в версии C99 языка C)const uint64_t m1  = 0x5555555555555555; // двоичный: 0101 ...const uint64_t m2  = 0x3333333333333333; // двоичный: 00110011 ..const uint64_t м4  = 0x0f0f0f0f0f0f0f0f; // двоичный: 4 нуля, 4 единицы ...const uint64_t m8  = 0x00ff00ff00ff00ff; // двоичный код: 8 нулей, 8 единиц ...const uint64_t m16 = 0x0000ffff0000ffff; // двоичный код: 16 нулей, 16 единиц ...const uint64_t m32 = 0x00000000ffffffff; // двоичный: 32 нуля, 32 единицыconst uint64_t h01 = 0x0101010101010101; // сумма 256 в степени 0,1,2,3 ...// Это наивная реализация, показанная для сравнения,// и помочь в понимании лучших функций.// Этот алгоритм использует 24 арифметических операции (сдвиг, сложение и).int popcount64a(uint64_t Икс){    Икс = (Икс & m1 ) + ((Икс >>  1) & m1 ); // помещаем количество каждых 2 бита в эти 2 бита     Икс = (Икс & m2 ) + ((Икс >>  2) & m2 ); // помещаем количество каждых 4 бита в эти 4 бита     Икс = (Икс & м4 ) + ((Икс >>  4) & м4 ); // помещаем количество каждых 8 бит в эти 8 бит     Икс = (Икс & m8 ) + ((Икс >>  8) & m8 ); // помещаем количество каждых 16 бит в эти 16 бит     Икс = (Икс & m16) + ((Икс >> 16) & m16); // помещаем количество каждых 32 бита в эти 32 бита     Икс = (Икс & m32) + ((Икс >> 32) & m32); // помещаем количество каждых 64 бит в эти 64 бита     возвращаться Икс;}// Здесь используется меньше арифметических операций, чем в любых других известных // реализация на машинах с медленным умножением.// Этот алгоритм использует 17 арифметических операций.int popcount64b(uint64_t Икс){    Икс -= (Икс >> 1) & m1;             // помещаем количество каждых 2 бита в эти 2 бита    Икс = (Икс & m2) + ((Икс >> 2) & m2); // помещаем количество каждых 4 бита в эти 4 бита     Икс = (Икс + (Икс >> 4)) & м4;        // помещаем количество каждых 8 бит в эти 8 бит     Икс += Икс >>  8;  // помещаем количество каждых 16 бит в самые младшие 8 бит    Икс += Икс >> 16;  // помещаем количество каждых 32 бита в самые младшие 8 бит    Икс += Икс >> 32;  // помещаем количество каждых 64 бит в самые младшие 8 бит    возвращаться Икс & 0x7f;}// Здесь используется меньше арифметических операций, чем в любых других известных // реализация на машинах с быстрым умножением.// Этот алгоритм использует 12 арифметических операций, одна из которых - умножение.int popcount64c(uint64_t Икс){    Икс -= (Икс >> 1) & m1;             // помещаем количество каждых 2 бита в эти 2 бита    Икс = (Икс & m2) + ((Икс >> 2) & m2); // помещаем количество каждых 4 бита в эти 4 бита     Икс = (Икс + (Икс >> 4)) & м4;        // помещаем количество каждых 8 бит в эти 8 бит     возвращаться (Икс * h01) >> 56;  // возвращает 8 левых битов x + (x << 8) + (x << 16) + (x << 24) + ... }

Вышеупомянутые реализации имеют лучшее поведение в худшем случае из всех известных алгоритмов. Однако, когда ожидается, что значение будет иметь несколько ненулевых битов, вместо этого может быть более эффективным использовать алгоритмы, которые подсчитывают эти биты по одному. Как описал Вегнер в 1960 году,[13] в побитовое И из Икс с Икс – 1 отличается от Икс только при обнулении младшего значащего ненулевого бита: вычитание 1 изменяет крайнюю правую строку из 0 на 1 и заменяет крайнюю правую 1 на 0. Если Икс изначально имел п биты, которые были равны 1, то только после п итерации этой операции, Икс будет сведено к нулю. Следующая реализация основана на этом принципе.

// Это лучше, когда большинство бит в x равны 0// Этот алгоритм работает одинаково для всех размеров данных.// Этот алгоритм использует 3 арифметических операции и 1 сравнение / переход на 1 бит в x.int popcount64d(uint64_t Икс){    int считать;    за (считать=0; Икс; считать++)        Икс &= Икс - 1;    возвращаться считать;}

Если разрешено большее использование памяти, мы можем вычислить вес Хэмминга быстрее, чем описанные выше методы. Имея неограниченную память, мы могли бы просто создать большую таблицу поиска веса Хэмминга для каждого 64-битного целого числа. Если мы можем сохранить таблицу поиска функции Хэмминга для каждого 16-битного целого числа, мы можем сделать следующее, чтобы вычислить вес Хэмминга для каждого 32-битного целого числа.

статический uint8_t биты слов[65536] = { / * количество битов целых чисел от 0 до 65 535 включительно * / };// Этот алгоритм использует 3 арифметических операции и 2 чтения из памяти.int popcount32e(uint32_t Икс){    возвращаться биты слов[Икс & 0xFFFF] + биты слов[Икс >> 16];}
// По желанию, таблица wordbits [] может быть заполнена с помощью этой функцииint popcount32e_init(пустота){    uint32_t я;    uint16_t Икс;    int считать;    за (я=0; я <= 0xFFFF; я++)    {        Икс = я;        за (считать=0; Икс; считать++) // заимствовано из popcount64d () выше            Икс &= Икс - 1;        биты слов[я] = считать;    }}

Muła et al.[14] показали, что векторизованная версия popcount64b может работать быстрее, чем выделенные инструкции (например, popcnt на процессорах x64).

Языковая поддержка

Некоторые компиляторы C предоставляют встроенные функции, обеспечивающие подсчет битов. Например, GCC (начиная с версии 3.4 в апреле 2004 г.) включает встроенную функцию __builtin_popcount который будет использовать инструкцию процессора, если она доступна, или эффективную реализацию библиотеки в противном случае.[15] LLVM-GCC включает эту функцию с версии 1.5 в июне 2005 года.[16]

В C ++ STL, структура данных битового массива битсет имеет считать() метод, который подсчитывает количество установленных битов. В C ++ 20, новый заголовок <bit> был добавлен, содержащий функции std :: popcount и std :: has_single_bit, принимая аргументы беззнакового целого типа.

В Java структура данных растущего битового массива BitSet имеет BitSet.cardinality () метод, который подсчитывает количество установленных битов. Кроме того, есть Integer.bitCount (число) и Long.bitCount (длинный) функции для подсчета битов в примитивных 32-битных и 64-битных целых числах соответственно. Так же BigInteger целочисленный класс произвольной точности также имеет BigInteger.bitCount () метод, который считает биты.

В Python, то int тип имеет bit_count () метод для подсчета количества установленных битов. Эта функция является новой в Python 3.10, выпуск которой запланирован на 2021 год.[17]

В Common Lisp функция logcount, заданная неотрицательным целым числом, возвращает количество битов, равное единице. (Для отрицательных целых чисел он возвращает количество 0 бит в нотации дополнения до 2.) В любом случае целое число может быть BIGNUM.

Начиная с GHC 7.4, Haskell базовый пакет имеет popCount функция доступна для всех типов, которые являются экземплярами Биты класс (доступен из Data.Bits модуль).[18]

MySQL версия SQL язык обеспечивает BIT_COUNT () как стандартная функция.[19]

Фортран 2008 имеет стандартную внутреннюю элементарную функцию popcnt возвращает количество ненулевых битов в целочисленном (или целочисленном массиве).[20]

Некоторые программируемые карманные научные калькуляторы имеют специальные команды для вычисления количества установленных бит, например #B на HP-16C[3][21] и WP 43S,[22][23] # БИТЫ[24][25] или же BITSUM[26][27] на эмуляторах HP-16C и nBITS на WP 34S.[28][29]

FreePascal реализует popcnt начиная с версии 3.0.[30]

Поддержка процессора

  • В IBM STRETCH компьютер в 1960-х рассчитывал количество установленных битов, а также количество ведущих нулей как побочный продукт всех логических операций.[1]
  • Cray суперкомпьютеры на раннем этапе показали подсчет населения машинная инструкция, по слухам, был специально запрошен правительством США Национальное Агенство Безопасности за криптоанализ Приложения.[1]
  • Некоторые из Корпорация Control Data (CDC) Cyber ​​70/170 серийные машины включали инструкцию подсчета населения; в КОМПАС, эта инструкция была закодирована как CXi.
  • 64-битный SPARC архитектура версии 9 определяет POPC инструкция[11][1] но большинство реализаций не реализуют его, требуя, чтобы операционная система эмулировала его.[31]
  • Дональд Кнут модель компьютера MMIX это заменит СМЕШИВАНИЕ в его книге Искусство программирования имеет SADD инструкция с 1999 года. САДД a, b, c считает все биты, которые равны 1 в b и 0 в c, и записывает результат в a.
  • Compaq с Альфа 21264A, выпущенный в 1999 году, был первым процессором серии Alpha, который имел расширение count (CIX).
  • Аналоговые устройства ‘ Blackfin процессоры оснащены ОДИН инструкция для выполнения 32-битного подсчета населения.[32]
  • AMD с Барселона архитектура представила расширенную обработку битов (ABM) ЭТО представляя POPCNT инструкция как часть SSE4a расширений в 2007 году.
  • Intel Core процессоры представили POPCNT инструкция с SSE4.2 Набор инструкций расширение, впервые доступное в Nehalem -основан Core i7 процессор, выпущенный в ноябре 2008 года.
  • В ARM архитектура представил VCNT инструкция как часть Расширенный SIMD (НЕОН ) расширения.
  • В RISC-V архитектура представила PCNT инструкция как часть расширения Bit Manipulation (B).[33]

Смотрите также

  • Минимальный вес
  • Два дополнения
  • Наиболее часто встречающиеся символы k
  • Веером

Рекомендации

  1. ^ а б c d е ж грамм Уоррен-младший, Генри С. (2013) [2002]. Хакерское наслаждение (2-е изд.). Эддисон Уэсли – Pearson Education, Inc. С. 81–96. ISBN  978-0-321-84268-8. 0-321-84268-5.
  2. ^ Кнут, Дональд Эрвин (2009). «Побитовые приемы и методы. Диаграммы двоичных решений». Искусство программирования. Том 4, Часть 1. Эддисон – Уэсли Профессионал. ISBN  0-321-58050-8. (NB. Проект Пучок 1b доступны для скачивания.)
  3. ^ а б Руководство пользователя компьютерного ученого Hewlett-Packard HP-16C (PDF). Компания Hewlett-Packard. Апрель 1982 г. 00016-90001. В архиве (PDF) из оригинала от 28.03.2017. Получено 2017-03-28.
  4. ^ [1], написано на языке Frmulæ. Вики Сообщества. Проверено 30 сентября 2019.
  5. ^ Решение задачи Количество населения. Проверено 30 сентября 2019.
  6. ^ Розеттский код. Проверено 30 сентября 2019.
  7. ^ Томпсон, Томас М. (1983). От кодов с исправлением ошибок до сферических упаковок и простых групп. Математические монографии Каруса № 21. Математическая ассоциация Америки. п. 33.
  8. ^ Глейшер, Джеймс Уитбред Ли (1899). «О вычете коэффициента биномиальной теоремы относительно простого модуля». Ежеквартальный журнал чистой и прикладной математики. 30: 150–156. (NB. См., В частности, последний абзац на стр. 156.)
  9. ^ Рид, Ирвинг Стой (1954). «Класс кодов с множественными ошибками и схема декодирования». IRE Профессиональная группа по теории информации. Институт Радиоинженеров (IRE). ПГИТ-4: 38–49.
  10. ^ Stoica, I .; Morris, R .; Liben-Nowell, D .; Karger, D. R .; Kaashoek, M. F .; Дабек, Ф .; Балакришнан, Х. (февраль 2003 г.). «Chord: масштабируемый протокол однорангового поиска для интернет-приложений». Транзакции IEEE / ACM в сети. 11 (1): 17–32. Раздел 6.3: «В общем, количество пальцев, по которым нам нужно следовать, будет количеством единиц в двоичном представлении расстояния от узла до запроса».
  11. ^ а б SPARC International, Inc. (1992). «A.41: Счетчик населения. Примечание по программированию». Руководство по архитектуре SPARC: версия 8 (Версия 8-е изд.). Энглвуд Клиффс, Нью-Джерси, США: Prentice Hall. стр.231. ISBN  0-13-825001-4.
  12. ^ Блакселл, Дэвид (1978). Хогбен, Дэвид; Файф, Деннис В. (ред.). «Связывание записи по битовому шаблону». Компьютерные науки и статистика – десятый ежегодный симпозиум по интерфейсу. Специальное издание NBS. Министерство торговли США / Национальное бюро стандартов. 503: 146–156.
  13. ^ Вегнер, Питер (Май 1960 г.). «Методика счета единиц в двоичном компьютере». Коммуникации ACM. 3 (5): 322. Дои:10.1145/367236.367286.
  14. ^ Мула, Войцех; Курц, Натан; Лемир, Даниэль (январь 2018). «Ускоренный подсчет населения с помощью инструкций AVX2». Компьютерный журнал. 61 (1). arXiv:1611.07612. Дои:10.1093 / comjnl / bxx046.
  15. ^ «Примечания к выпуску GCC 3.4». Проект GNU.
  16. ^ «Примечания к выпуску LLVM 1.5». LLVM проект.
  17. ^ «Что нового в Python 3.10». python.org.
  18. ^ «Примечания к выпуску GHC 7.4.1». Документация GHC.
  19. ^ “Глава 12.11. Битовые функции – Справочное руководство MySQL 5.0”.
  20. ^ Меткалф, Майкл; Рид, Джон; Коэн, Малкольм (2011). Объяснение современного Фортрана. Oxford University Press. п. 380. ISBN  0-19-960142-9.
  21. ^ Шварц, Джейк; Гревелл, Рик (2003-10-20) [1993]. Библиотека эмулятора HP16C для HP48S / SX. 1.20 (1-е изд.). Получено 2015-08-15. (NB. Эта библиотека также работает на HP 48G /GX /G +. Помимо набора функций HP-16C этот пакет также поддерживает вычисления для двоичных, восьмеричных и шестнадцатеричных числа с плавающей запятой в научная нотация в дополнение к обычным десятичным числам с плавающей запятой.)
  22. ^ Бонин, Вальтер (2019) [2015]. WP 43S Руководство пользователя (PDF). 0,12 (черновик ред.). п. 135. ISBN  978-1-72950098-9. ISBN  1-72950098-6. Получено 2019-08-05. [2] [3] (314 стр.)
  23. ^ Бонин, Вальтер (2019) [2015]. Справочное руководство WP 43S (PDF). 0,12 (черновик ред.). С. xiii, 104, 115, 120, 188. ISBN  978-1-72950106-1. ISBN  1-72950106-0. Получено 2019-08-05. [4] [5] (271 стр.)
  24. ^ Martin, Ángel M .; МакКлюр, Грег Дж. (05.09.2015). «Модуль эмулятора HP16C для HP-41CX – Руководство пользователя и QRG» (PDF). В архиве (PDF) из оригинала от 27.04.2017. Получено 2017-04-27. (NB. За пределами HP-16C функция устанавливает эту настраиваемую библиотеку для HP-41CX расширяет функциональные возможности калькулятора примерно на 50 дополнительных функций.)
  25. ^ Мартин, Анхель М. (07.09.2015). «HP-41: доступен новый эмулятор HP-16C». В архиве из оригинала от 27.04.2017. Получено 2017-04-27.
  26. ^ Тёрнгрен, Хокан (10 января 2017 г.). “Божья коровка Документация” (выпуск 0А ред.). Получено 2017-01-29. [6]
  27. ^ «Доступен новый модуль HP-41: Божья коровка». 2017-01-10. В архиве из оригинала от 29.01.2017. Получено 2017-01-29.
  28. ^ Дейл, Пол; Бонин, Уолтер (2012) [2008]. «Руководство пользователя WP 34S» (PDF) (3,1 изд.). Получено 2017-04-27.
  29. ^ Бонин, Уолтер (2015) [2008]. WP 34S Руководство пользователя (3,3 изд.). ISBN  978-1-5078-9107-0.
  30. ^ “Free Pascal documentation popcnt”. Получено 2019-12-07.
  31. ^ “JDK-6378821: bitCount () должен использовать POPC на процессорах SPARC и AMD + 10h”. База данных ошибок Java. 2006-01-30.
  32. ^ Справочник по набору команд Blackfin (Предварительная ред.). Аналоговые устройства. 2001. С. 8–24. Каталожный номер 82-000410-14.
  33. ^ Вольф, Клиффорд (22 марта 2019 г.). “RISC-V” B “Расширение управления битами для RISC-V, проект v0.37” (PDF). Github.

дальнейшее чтение

  • Schroeppel, Ричард С.; Орман, Хилари К. (1972-02-29). “сборник”. HAKMEM. Билер, Майкл; Госпер, Ральф Уильям; Schroeppel, Ричард С. (отчет). Лаборатория искусственного интеллекта, Массачусетский Институт Технологий, Кембридж, Массачусетс, США. Записка Массачусетского технологического института по ИИ 239. (Штука 169: Код сборки подсчета населения для PDP / 6-10.)

внешняя ссылка

  • Агрегированные магические алгоритмы. Оптимизированный подсчет населения и другие алгоритмы, объясненные в образце кода.
  • Bit Twiddling Хаки Установлено несколько алгоритмов с кодом для подсчета битов.
  • Необходимые и достаточные – Дэмиен Винтур – Имеет код на C # для различных реализаций Веса Хэмминга.
  • Лучший алгоритм для подсчета количества установленных битов в 32-битном целом числе? – Переполнение стека

Добавить комментарий