Джава опубликовал эту идею изначально;вот моя попытка.
^
- это функция XOR.Он сравнивает 2 двоичных числа побитно и возвращает 0, если оба бита одинаковы, и 1 в противном случае.
0 1 0 0 0 1 0 1 0 1 1 1 (number 1)
^ 0 1 1 1 0 1 0 1 1 0 1 1 (number 2)
= 0 0 1 1 0 0 0 0 1 1 0 0 (result)
Как это относится к вашей проблеме:
// In binary...
1111 ^ 0111 = 1000 // (1 bit out of 4 didn't match: 75% match)
1111 ^ 0000 = 1111 // (4 bits out of 4 didn't match: 0% match)
// The same examples, except now in decimal...
15 ^ 7 = 8 (1000 in binary) // (1 bit out of 4 didn't match: 75% match)
15 ^ 0 = 15 (1111 in binary) // (4 bits out of 4 didn't match: 0% match)
Какмы можем сосчитать эти биты в MySQL:
BIT_COUNT(b'0111') = 3 // Bit count of binary '0111'
BIT_COUNT(7) = 3 // Bit count of decimal 7 (= 0111 in binary)
BIT_COUNT(b'1111' ^ b'0111') = 1 // (1 bit out of 4 didn't match: 75% match)
Таким образом, чтобы получить сходство ...
// First we focus on calculating mismatch.
(BIT_COUNT(b'1111' ^ b'0111') / YOUR_TOTAL_BITS) = 0.25 (25% mismatch)
(BIT_COUNT(b'1111' ^ b'1111') / YOUR_TOTAL_BITS) = 0 (0% mismatch; 100% match)
// Now, getting the proportion of matched bits is easy
1 - (BIT_COUNT(b'1111' ^ b'0111') / YOUR_TOTAL_BITS) = 0.75 (75% match)
1 - (BIT_COUNT(b'1111' ^ b'1111') / YOUR_TOTAL_BITS) = 1.00 (100% match)
Если бы мы могли просто сделать ваше поле about_member
хранить данные в виде битов (и быть представлены целым числом), мы могли бы сделать все это легко!Вместо 1-2-1-1-1
используйте 0-1-0-0-0
, но без тире.
Вот как PHP может помочь нам:
bindec('01000') == 8;
bindec('00001') == 1;
decbin(8) == '01000';
decbin(1) == '00001';
И, наконец, вот реализация:
// Setting a member's about_member property...
$about_member = '01100101';
$about_member_int = bindec($about_member);
$query = "INSERT INTO members (name,about_member) VALUES ($name,$about_member_int)";
// Getting matches...
$total_bits = 8; // The maximum length the member_about field can be (8 in this example)
$my_member_about = '00101100';
$my_member_about_int = bindec($my_member_about_int);
$query = "
SELECT
*,
(1 - (BIT_COUNT(member_about ^ $my_member_about_int) / $total_bits)) match
FROM members
ORDER BY match DESC
LIMIT 10";
Этот последний запрос выберет 10 членов, наиболее похожих на меня!
Теперь, если говорить кратко, с точки зрения непрофессионала,
Мы используем двоичный файл, потому что онделает вещи проще;двоичное число похоже на длинную линию выключателей света.Мы хотим сохранить нашу «конфигурацию выключателя света», а также найти членов, которые имеют наиболее похожие конфигурации.
Оператор ^
, учитывая две конфигурации выключателя света, делает для нас сравнение.Результатом снова является серия переключателей;переключатель будет ON
, если 2 исходных переключателя находились в разных положениях, и OFF
, если они были в одинаковом положении.
BIT_COUNT
говорит нам, сколько переключателей ON
- даваянам подсчитать, сколько переключателей были разные.YOUR_TOTAL_BITS
- это общее количество переключателей.
Но двоичные числа - это просто числа ... и поэтому строка из 1 и 0 на самом деле просто представляет число, подобное 133 или 94. Но это намного сложнееВизуализируйте нашу «конфигурацию выключателя света», если мы используем десятичные числа.Вот где появляются PHP decbin
и bindec
.
Узнайте больше о двоичной системе счисления.
Надеюсь, это поможет!