Вес Хэмминга
Эта статья нуждается в дополнительных цитатах для проверки . ( январь 2009 г. ) |
Вес Хэмминга строки — это количество символов, отличных от нулевого символа используемого алфавита . Таким образом, оно эквивалентно расстоянию Хэмминга от нулевой строки той же длины. Для наиболее типичного случая, строки битов , это количество единиц в строке или сумма цифр двоичного представления данного числа и нормы ℓ ₁ битового вектора. В этом двоичном случае его также называют подсчетом населения , [1] popcount , боковая сумма , [2] или суммирование битов . [3]
Нить | Вес Хэмминга |
---|---|
111 0 1 | 4 |
111 0 1 000 | 4 |
00000000 | 0 |
678 0 1234 0 567 | 10 |
История и использование
[ редактировать ]Гиря Хэмминга названа в честь Ричарда Хэмминга, хотя это понятие принадлежит не ему. [5] Вес Хэмминга двоичных чисел уже использовался в 1899 году Джеймсом Глейшером для получения формулы для количества нечетных биномиальных коэффициентов в одной строке треугольника Паскаля . [6] Ирвинг С. Рид ввел концепцию, эквивалентную весу Хэмминга в двоичном случае, в 1954 году. [7]
Вес Хэмминга используется в нескольких дисциплинах, включая теорию информации , теорию кодирования и криптографию . Примеры применения веса Хэмминга включают:
- При модульном возведении в степень возведением в квадрат количество модульных умножений, необходимых для показателя e, равно log 2 e + Weight( e ). По этой причине значение открытого ключа e, используемое в RSA, обычно выбирается как число с низким весом Хэмминга. [8]
- Вес Хэмминга определяет длину путей между узлами в распределенных хеш-таблицах Chord . [9]
- Поиск IrisCode в биометрических базах данных обычно реализуется путем расчета расстояния Хэмминга до каждой сохраненной записи.
- В компьютерных шахматных программах, использующих представление битовой доски , вес Хэмминга битовой доски дает количество фигур данного типа, оставшихся в игре, или количество клеток доски, контролируемых фигурами одного игрока, и, следовательно, является важным способствующим фактором. к стоимости позиции.
- Вес Хэмминга можно использовать для эффективного вычисления первого набора поиска, используя тождество ffs(x) = pop(x ^ (x - 1)). Это полезно на таких платформах, как SPARC , где есть аппаратные инструкции по весу Хэмминга, но нет аппаратных инструкций по поиску первого набора. [10] [1]
- Весовую операцию Хэмминга можно интерпретировать как преобразование унарной системы счисления в двоичную систему чисел . [11]
- В реализации некоторых кратких структур данных, таких как битовые векторы и деревья вейвлетов .
Эффективная реализация
[ редактировать ]Подсчет численности битовой строки часто необходим в криптографии и других приложениях. Расстояние Хэмминга двух слов A и B можно рассчитать как вес Хэмминга A xor B . [1]
Проблема его эффективной реализации широко изучена. одна операция вычисления или параллельные операции над битовыми векторами На некоторых процессорах доступны . Для процессоров, лишенных этих функций, лучшие известные решения основаны на добавлении счетчиков в древовидную структуру. Например, чтобы подсчитать количество 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 | Каждый второй счет от e | ||||||
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, а + — обычное сложение. Лучшие алгоритмы, известные для решения этой проблемы, основаны на концепции, проиллюстрированной выше, и приведены здесь: [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) + ...
}
Вышеупомянутые реализации имеют лучшее поведение в наихудшем случае из всех известных алгоритмов. Однако, когда ожидается, что значение будет иметь несколько ненулевых битов, вместо этого может быть более эффективно использовать алгоритмы, которые считают эти биты по одному. Как описал Вегнер в 1960 году, [12] побитовое И для 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;
}
}
Мула и др. [13] показали, что векторизованная версия popcount64b может работать быстрее, чем специальные инструкции (например, popcnt на процессорах x64).
Минимальный вес
[ редактировать ]В кодировании с исправлением ошибок минимальный вес Хэмминга, обычно называемый минимальным весом w min кода, представляет собой вес ненулевого кодового слова с наименьшим весом. Вес w кодового слова — это количество единиц в слове. Например, слово 11001010 имеет вес 4.
В линейном блочном коде минимальный вес также является минимальным расстоянием Хэмминга ( d min ) и определяет способность кода исправлять ошибки. Если w min = n , то d min = n и код исправит до d min /2 ошибок. [14]
Языковая поддержка
[ редактировать ]Некоторые компиляторы C предоставляют встроенные функции, обеспечивающие подсчет битов. Например, GCC (начиная с версии 3.4 в апреле 2004 г.) включает встроенную функцию __builtin_popcount
который будет использовать инструкцию процессора, если она доступна, или эффективную реализацию библиотеки в противном случае. [15] LLVM-GCC включает эту функцию начиная с версии 1.5 в июне 2005 года. [16]
В стандартной библиотеке C++ структура данных битового массива 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 года. [17]
В Common Lisp функция logcount
, учитывая неотрицательное целое число, возвращает количество 1 бит. (Для отрицательных целых чисел возвращается количество нулевых битов в записи дополнения до 2.) В любом случае целое число может быть БОЛЬШИМ ЧИСЛОМ.
Начиная с GHC 7.4, базовый пакет Haskell имеет popCount
функция доступна для всех типов, которые являются экземплярами Bits
класс (доступен на Data.Bits
модуль). [18]
MySQL- версия языка SQL обеспечивает BIT_COUNT()
как стандартная функция. [19]
Фортран 2008 имеет стандартную, внутреннюю, элементарную функцию. popcnt
возврат количества ненулевых битов в целом числе (или целочисленном массиве). [20]
Некоторые программируемые карманные научные калькуляторы имеют специальные команды для расчета количества установленных бит, например #B
на НР-16С [3] [21] и WP 43S , [22] [23] #BITS
[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 Corporation (CDC) Машины серий 6000 и Cyber 70/170 включали команду подсчета населения; в COMPASS эта инструкция была закодирована как
CXi
. - 64-битная архитектура SPARC версии 9 определяет
POPC
инструкция, [10] [1] но большинство реализаций не реализуют его, требуя его эмуляции операционной системой. [31] - Дональда Кнута Модель компьютера MMIX , которая заменит MIX в его книге «Искусство компьютерного программирования», имеет
SADD
обучение с 1999 года.SADD a,b,c
подсчитывает все биты, равные 1 в b и 0 в c, и записывает результат в a. - Compaq компании Alpha 21264A , выпущенный в 1999 году, был первым процессором серии Alpha, который имел расширение счетчика (
CIX
). - Analog Devices от Процессоры Blackfin оснащены
ONES
инструкция для выполнения 32-битного подсчета населения. [32] - Архитектура AMD Barcelona . усовершенствованную битовую манипуляцию (ABM) ISA представила
POPCNT
инструкция как часть расширений SSE4a в 2007 году. - Intel Core представили Процессоры
POPCNT
Инструкция с SSE4.2 расширением набора команд , впервые доступная в Nehalem на базе процессоре Core i7 , выпущенном в ноябре 2008 года. - Архитектура ARM представила
VCNT
инструкция как часть расширений Advanced SIMD ( NEON ). - Архитектура RISC-V представила
CPOP
инструкция как часть расширения Bit Manipulation (B). [33]
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ Jump up to: а б с д и ж г Уоррен-младший, Генри С. (2013) [2002]. Хакерское наслаждение (2-е изд.). Аддисон Уэсли - Pearson Education, Inc., стр. 81–96. ISBN 978-0-321-84268-8 . 0-321-84268-5.
- ^ Кнут, Дональд Эрвин (2009). «Побитовые приемы и методы; Двоичные диаграммы решений». Искусство компьютерного программирования . Том. 4, выпуск 1. Addison-Wesley Professional . ISBN 978-0-321-58050-4 . (Примечание. Черновик главы 1b, заархивированный 12 марта 2016 г. на Wayback Machine , доступен для скачивания.)
- ^ Jump up to: а б Руководство пользователя Hewlett-Packard HP-16C для компьютерных специалистов (PDF) . Компания Хьюлетт-Паккард . Апрель 1982 г. 00016-90001. Архивировано (PDF) из оригинала 28 марта 2017 г. Проверено 28 марта 2017 г.
- ^ Р.Угальде, Лоуренс. «Подсчет населения языка программирования Fōrmulæ» . Формулы . Проверено 2 июня 2024 г.
- ^ Томпсон, Томас М. (1983). От кодов, исправляющих ошибки, через сферические упаковки к простым группам . Математические монографии Каруса № 21. Математическая ассоциация Америки . п. 33.
- ^ Глейшер, Джеймс Уитбред Ли (1899). «О вычете коэффициента биномиальной теоремы по простому модулю» . Ежеквартальный журнал чистой и прикладной математики . 30 : 150–156. (Примечание. См., в частности, последний абзац стр. 156.)
- ^ Рид, Ирвинг Стой (1954). «Класс кодов, исправляющих множественные ошибки, и схема декодирования». Профессиональная группа IRE по теории информации . ПГИТ-4. Институт радиоинженеров (ИРЭ): 38–49.
- ^ Коэн, Жерар Д .; Лобштейн, Антуан; Наккеш, Дэвид; Земор, Жиль (1998). «Как улучшить черный ящик возведения в степень». В Нюберге, Кайса (ред.). Достижения в криптологии – EUROCRYPT '98, Международная конференция по теории и применению криптографических методов, Эспоо, Финляндия, 31 мая – 4 июня 1998 г., Текущие материалы . Конспекты лекций по информатике. Том. 1403. Спрингер. стр. 211–220. дои : 10.1007/BFb0054128 . ISBN 978-3-540-64518-4 .
- ^ Стойка, И.; Моррис, Р.; Либен-Ноуэлл, Д.; Каргер, доктор медицинских наук; Каашук, МФ; Дабек, Ф.; Балакришнан, Х. (февраль 2003 г.). «Chord: масштабируемый протокол однорангового поиска для интернет-приложений». Транзакции IEEE/ACM в сети . 11 (1): 17–32. дои : 10.1109/TNET.2002.808407 . S2CID 221276912 .
Раздел 6.3: «В общем, количество пальцев, за которыми нам нужно следовать, будет равно числу единиц в двоичном представлении расстояния от узла до запроса».
- ^ Jump up to: а б SPARC International, Inc. (1992). «A.41: Подсчет населения. Примечание по программированию» . Руководство по архитектуре SPARC: версия 8 (изд. версии 8). Энглвуд Клиффс, Нью-Джерси, США: Прентис Холл . стр. 231 . ISBN 0-13-825001-4 .
- ^ Блэкселл, Дэвид (1978). Хогбен, Дэвид; Файф, Деннис В. (ред.). «Связывание записей по битовому шаблону» . Информатика и статистика — Десятый ежегодный симпозиум по интерфейсу . Специальное издание НБС. 503 . Министерство торговли США / Национальное бюро стандартов : 146–156.
- ^ Вегнер, Питер (май 1960 г.). «Техника счета единиц в двоичном компьютере» . Коммуникации АКМ . 3 (5): 322. дои : 10.1145/367236.367286 . S2CID 31683715 .
- ^ Мула, Войцех; Курц, Натан; Лемир, Дэниел (январь 2018 г.). «Более быстрый подсчет населения с использованием инструкций AVX2». Компьютерный журнал . 61 (1): 111–120. arXiv : 1611.07612 . дои : 10.1093/comjnl/bxx046 . S2CID 540973 .
- ^ Стерн и Махмуд, Проектирование систем связи , Prentice Hall , 2004, стр. 477 и далее.
- ^ «Примечания к выпуску GCC 3.4» . Проект ГНУ .
- ^ «Примечания к выпуску LLVM 1.5» . Проект ЛЛВМ .
- ^ «Что нового в Python 3.10» . python.org .
- ^ «Примечания к выпуску GHC 7.4.1» . Документация ГХК.
- ^ «Глава 12.11. Битовые функции — Справочное руководство MySQL 5.0» .
- ^ Меткалф, Майкл; Рид, Джон; Коэн, Малькольм (2011). Объяснение современного Фортрана . Издательство Оксфордского университета . п. 380. ИСБН 978-0-19-960142-4 .
- ^ Шварц, Джейк; Гревель, Рик (20 октября 2003 г.) [1993]. Библиотека эмулятора HP16C для HP48S/SX . 1.20 (1-е изд.) . Проверено 15 августа 2015 г. (Примечание. Эта библиотека также работает на HP 48G / GX / G+ . Помимо набора функций HP-16C, этот пакет также поддерживает вычисления для двоичных, восьмеричных и шестнадцатеричных чисел с плавающей запятой в экспоненциальном представлении в дополнение к обычным десятичным числам. числа с плавающей запятой.)
- ^ Бонин, Уолтер (2019) [2015]. Руководство пользователя WP 43S (PDF) . 0,12 (проект ред.). п. 135. ИСБН 978-1-72950098-9 . Проверено 5 августа 2019 г. [ постоянная мертвая ссылка ] [1] [2] (314 страниц)
- ^ Бонин, Уолтер (2019) [2015]. Справочное руководство WP 43S (PDF) . 0,12 (проект ред.). стр. XIII, 104, 115, 120, 188. ISBN. 978-1-72950106-1 . Проверено 5 августа 2019 г. [ постоянная мертвая ссылка ] [3] [4] (271 страница)
- ^ Мартин, Анхель М.; МакКлюр, Грег Дж. (5 сентября 2015 г.). «Модуль эмулятора HP16C для HP-41CX — Руководство пользователя и QRG» (PDF) . Архивировано (PDF) из оригинала 27 апреля 2017 г. Проверено 27 апреля 2017 г. (Примечание. Помимо набора функций HP-16C , эта специальная библиотека для HP-41CX расширяет функциональность калькулятора примерно на 50 дополнительных функций.)
- ^ Мартин, Анхель М. (07 сентября 2015 г.). «HP-41: доступен новый эмулятор HP-16C» . Архивировано из оригинала 27 апреля 2017 г. Проверено 27 апреля 2017 г.
- ^ Торнгрен, Хокан (10 января 2017 г.). «Документация по божьей коровке» (выпуск 0А изд.) . Проверено 29 января 2017 г. [5]
- ^ «Доступен новый модуль HP-41: Божья коровка» . 10 января 2017 г. Архивировано из оригинала 29 января 2017 г. Проверено 29 января 2017 г.
- ^ Дейл, Пол; Бонин, Уолтер (2012) [2008]. «Руководство пользователя WP 34S» (PDF) (изд. 3.1) . Проверено 27 апреля 2017 г.
- ^ Бонин, Уолтер (2015) [2008]. Руководство пользователя WP 34S (изд. 3.3). Независимая издательская платформа CreateSpace. ISBN 978-1-5078-9107-0 .
- ^ «Документация по Free Pascal popcnt» . Проверено 7 декабря 2019 г.
- ^ «JDK-6378821: bitCount() должен использовать POPC на процессорах SPARC и AMD+10h» . База данных ошибок Java . 30 января 2006 г.
- ^ Справочник по набору инструкций Blackfin (предварительное издание). Аналоговые устройства . 2001. стр. 8–24. Номер детали 82-000410-14.
- ^ Вольф, Клэр (22 марта 2019 г.). Расширение битовых манипуляций RISC-V «B» для RISC-V, черновик v0.37» (PDF) . Гитхаб .
Дальнейшее чтение
[ редактировать ]- Шреппель, Ричард К .; Орман, Хилари К. (29 февраля 1972 г.). «сборник». ХАКМЕМ . Билер, Майкл; Госпер, Ральф Уильям ; Шреппель, Ричард К. (отчет). искусственного интеллекта Лаборатория Массачусетского технологического института , Кембридж, Массачусетс, США. Памятка MIT AI 239. ( Поз. 169 : Код сборки подсчета населения для PDP/6-10.)
Внешние ссылки
[ редактировать ]- Агрегатные магические алгоритмы . Оптимизированный подсчет населения и другие алгоритмы, объясненные с помощью примера кода.
- Bit Twiddling Hacks Несколько алгоритмов с набором кода для подсчета битов.
- Необходимое и достаточное. Архивировано 23 сентября 2017 г. в Wayback Machine. Автор: Дэмиен Винтур. Содержит код на C# для различных реализаций веса Хэмминга.
- Лучший алгоритм для подсчета количества установленных бит в 32-битном целом числе? - Переполнение стека