Быстрый расчет расстояния Хэмминга в C
я читал статью Википедии на Вес Хэмминга и заметил кое-что интересное:
таким образом эквивалентно
Hamming distanceиз строки all-zero одинаковой длины. Для наиболее типичного случая, строка битов, это число 1 в строке. В этом двоичный случай, он также называется количеством населения,popcountили в сторону Сум.[акцент мой]
так что мне кое-что пришло в голову. Могу ли я вычислить расстояние Хэмминга между двумя строками по XORing их, а затем принимая вес Хэмминга (POPCOUNT) результирующей строки?
что-то в этом роде (используя gcc intrinsics):
#include <stdint.h>
int hammingDistance (uint64_t x, uint64_t y) {
uint64_t res = x ^ y;
return __builtin_popcountll (res);
}
теперь, что касается того, почему я хотел бы сделать это, ну, на некоторых платформах, да, это было просто переводить gcc испускание вызова функции, которая вычисляет popcount. Например, на x64 без popcnt, gcc выплевывает (GODBOLT's GCC Online):
hammingDistance:
sub rsp, 8
xor rdi, rsi
call __popcountdi2
add rsp, 8
ret
OTOH, если у вас есть платформа, поддерживающая POPCOUNT, например модели x64, включая nehalem и после (которые POPCNT), вы получаете (GODBOLT's GCC Online):
hammingDistance:
xor rdi, rsi
popcnt rax, rdi
ret
который должен быть waaay быстрее, особенно после ввода.
Но вернемся к изначальному вопросу. Можешь взять Хэмминг? Вес XOR двух строк, чтобы найти их расстояние Хэмминга? т. е.:
HD = HW (x xor y)
2 ответов
расстояние Хэмминга между двумя строками равной длины,x и y, определяется как количество позиций, в которых они отличаются. В случае x и y будучи bitstrings, x^y является строкой с 1s в точно положениях они отличаются. Таким образом, HammingDistance(x,y) = Number of 1s in x^y, для bitstrings. Кроме того,HammingWeight(x) = number of 1s in x для bitstring x. Таким образом, ваше первое требование,HammingDistance(x,y) = HammingWeight(x^y) верно для bitstrings. Установив это, ясно, что ваша реализация верна.
Да, это работает. Для каждого бита, бит равен 1, если и только если входные биты различны. Следовательно, применительно к целому битовому вектору результат имеет столько же битов (HW), сколько входы имеют разные биты (HD). И ваш код, похоже, отлично использует эти отношения. Фактически, этот ярлык даже упоминается далее в статье веса Хэмминга, на которую вы ссылаетесь (эффективная реализация):
расстояние Хэмминга двух слов A и B может быть вычисляется как вес Хэмминга xor B.