Подсчет битов, установленных параллельно
unsigned int v; // count bits set in this (32-bit value)
unsigned int c; // store the total here
static const int S[] = {1, 2, 4, 8, 16}; // Magic Binary Numbers
static const int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
c = v - ((v >> 1) & B[0]);
c = ((c >> S[1]) & B[1]) + (c & B[1]);
c = ((c >> S[2]) + c) & B[2];
c = ((c >> S[3]) + c) & B[3];
c = ((c >> S[4]) + c) & B[4];
The B массива, выраженное в двоичной форме, является:
B[0] = 0x55555555 = 01010101 01010101 01010101 01010101
B[1] = 0x33333333 = 00110011 00110011 00110011 00110011
B[2] = 0x0F0F0F0F = 00001111 00001111 00001111 00001111
B[3] = 0x00FF00FF = 00000000 11111111 00000000 11111111
B[4] = 0x0000FFFF = 00000000 00000000 11111111 11111111
Мы можем настроить метод для больших целых размеров на продолжая шаблоны для двоичных магических чисел, B и S. Если есть k бит, нам нужны массивы S и B, чтобы быть потолочными (lg (k)) элементами длинными, и мы должны вычислить одинаковое количество выражений для c, поскольку S или B являются длинными. Для 32-битного v используются 16 операций. Лучший метод для подсчета битов в 32-разрядное целое число V является следующее:
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
Лучший метод бита подсчета занимает всего 12 операций, которая является такой же, как метод поиска стола, но избегает память и потенциальные недостатки кэша таблицы. Это гибрид между чисто параллельным методом выше и более ранними методами с использованием умножений (в разделе о подсчете битов с 64-битными инструкциями), хотя он не использует 64-битные инструкции. Количество бит, заданное в байтах, выполняется параллельно, а сумма битов, установленных в байтах, вычисляется путем умножения на 0x1010101 и смещения правых 24 бит.
Обобщенные лучший бит методом подсчета на целых битовых ширины Шифрование до 128 (параметризовано типа Т) заключается в следующем:
v = v - ((v >> 1) & (T)~(T)0/3); // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count
Что тип данных это номер? –
Номер сохраняется как ulong – Thomas
Вы можете сдвинуть вправо до тех пор, пока число> 0 и сравнить число & (uint) 0x1 каждый раз (включая до первой смены). Кроме того, вы можете переместить 63 раза и использовать разворот цикла для предотвращения ветвлений в коде. –