比较“相似”的两个数字

时间:2011-09-05 22:52:49

标签: algorithm math pattern-matching matching

这是网站搜索功能的一部分。因此,我试图找到一种尽可能快地达到最终结果的方法。

有一个数字顺序重要的二进制数字。

输入数字= 01001

拥有一个长度相同的其他二进制数的数据库。

01000,10110,00000,11111

我不知道怎么写我正在做什么,所以我将在下面更直观地做。

// Zeros mean nothing & the location of a 1 matters, not the total number of 1's.    
input num > 0 1 0 0 1 = 2 possible matches
number[1] > 0 1 0 0 0 = 1 match = 50% match
number[2] > 1 0 1 1 0 = 0 match = 0% match
number[3] > 0 0 0 0 0 = 0 match = 0% match
number[4] > 1 1 1 1 1 = 2 match = 100% match

现在很明显,你可以逐个数字,逐个数字地进行比较,然后用这个方式进行比较(使用循环和不循环)。但我希望可能有一种算法或其他有用的东西。主要是因为在上面的例子中我只使用了5位数字。但我会定期比较大约100,000个数字,每个数字200个数字,这是很多计算。

我通常处理php和MySQL。但如果出现了一些壮观的东西,我总能学习。

5 个答案:

答案 0 :(得分:4)

如果有可能以某种方式在整数大小的块中切断你的位串,那么一些基本的布尔运算会做,而且那种指令通常很快

$matchmask = ~ ($inputval ^ $tomatch) & $inputval

这是做什么的:

  • xor确定inputval和tomatch中不同的位
  • 否定给出一个值,其中inputval和tomatch中相等的所有位都设置为
  • 和inputval,只有inputval和tomatch中的1位保持设置。

然后计算结果中设置的位数,查看How to count the number of set bits in a 32-bit integer?以获得最佳解决方案,轻松翻译成php

答案 1 :(得分:1)

嗯,我能想到的第一件事是两个数字之间的简单按位AND;然后,您可以分析结果以获得匹配百分比:

if( result >= input ) 
    //100% match
else {
    result ^= input;

    /* The number of 1's in result is the number of 1 of "input" 
     * that are missing in "result".
     */
}

当然,您需要实现自己的AND和XOR函数(这仅适用于32位整数)。请注意,它仅适用于无符号数字。

答案 2 :(得分:1)

您可以预先处理输入并确定需要检查的位,而不是检查每个位。在最坏的情况下,这将转换为处理每个位,但对于正态分布,您将节省一些处理。

即输入

01001,迭代数据库并确定number1[0] & input是否为非零,(number1[3] >> 8) & input为非零,假设0为LSB的索引。然而,你如何获得快速的位移和大数量的和谐。如果在输入中检测到1而不是0,则可以始终反转输入并测试零以检测覆盖范围。

这将为您提供适度的改进,但它最多可以持续减少问题。如果您的大多数输入在0和1之间平衡,则您将所需操作的数量减半。如果它更有偏见,你会得到更好的结果。

答案 3 :(得分:0)

假设输入数字称为A(在您的示例中为A = 01001),另一个数字为x。 x & A == A时,您将100%匹配。否则,对于部分匹配,1位的数量将取自黑客的喜悦:

x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
x = (x & 0x0000FFFF) + ((x >>16) & 0x0000FFFF);

注意这适用于32位整数。

答案 4 :(得分:0)

我们假设您有一个函数bit1count,然后根据您的描述,“相似”公式应为:

100.0 / min(bit1count(n1), bit1count(n2)) * bit1count(n1 & n2)

n1n2是两个数字,&是逻辑和运算符。

bit1count可以使用循环轻松实现,或者更优雅,使用BigBears答案中提供的算法。

mysql中实际上有一个BIT_COUNT,所以这样的东西应该可以工作:

SELECT 100.0 / IF(BIT_COUNT(n1) < BIT_COUNT(n2), BIT_COUNT(n1), BIT_COUNT(n2)) * BIT_COUNT(n1 & n2) FROM table