Быстрый расчет расстояния Хэмминга в C
я читал статью Википедии на Вес Хэмминга и заметил кое-что интересное:
таким образом эквивалентно
Hamming distance
из строки all-zero одинаковой длины. Для наиболее типичного случая, строка битов, это число 1 в строке. В этом двоичный случай, он также называется количеством населения,popcount
или в сторону Сум.[акцент мой]
так что мне кое-что пришло в голову. Могу ли я вычислить расстояние Хэмминга между двумя строками по XOR
ing их, а затем принимая вес Хэмминга (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
является строкой с 1
s в точно положениях они отличаются. Таким образом, 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.