【问题标题】:Mysql hamming distance of hexadecimal values十六进制值的Mysql汉明距离
【发布时间】:2015-09-06 08:10:28
【问题描述】:

我在 mysql 中存储了一些哈希值,我将通过汉明距离进行比较来获取这些哈希值。

存储的哈希值如下:

qw 1 ffe71b001820a1fd 
qw 2 ffffb81c1c3838a0 
qw 3 fff8381c1c3e3828 
qw 4 fffa181c3c2e3920 
qw 5 fffa981c1c3e2820 
qw 6 ff5f1c38387c1c04 
qw 7 fff1e0c1c38387ef 
qw 8 fffa181c1c3e3820 
qw 9 fffa381c1c3e3828

我通常会像这样获取:

SELECT product_id, HAMMING_DISTANCE(phash, 'phashfromuserinput') ;

但在 mysql 中,汉明距离是按位运算符,如果字符串只是数字,我可以这样做:

SELECT pagedata,BIT_COUNT(pagecontent^'$encrypted')searchengine WHERE pagecontent > 2 ; ")

它只适用于整数(数字),但我的要求是使用数字和字母,例如:

74898fababfbef46 and 95efabfeba752545

根据我的小研究,我知道首先我必须将字段转换为binary,然后通过使用CASTCONVERT 来使用bitcount,例如:

SELECT BIT_COUNT( CONV( hash, 2, 10 ) ^ 
0b0000000101100111111100011110000011100000111100011011111110011011 )

SELECT BIT_COUNT(CAST(hash AS BINARY)) FROM data;

这可以将数据转换为binary 并使用bitcount。现在问题出现了,存储在mysql 中的varbinary 字符/哈希已经是字母数字,如果我将字段转换为varbinarybitcount,那么它将不起作用,因为存储的哈希不是二进制字符串。

我该怎么办?

我指的是 php hamming 距离匹配示例:

function HammingDistance($bin1, $bin2) {
    $a1 = str_split($bin1);
    $a2 = str_split($bin2);
    $dh = 0;
    for ($i = 0; $i < count($a1); $i++) 
        if($a1[$i] != $a2[$i]) $dh++;
    return $dh;
}

echo HammingDistance('10101010','01010101'); //returns 8

但是我不明白如何与mysql匹配并获取,因为我无法在mysql中实现。

【问题讨论】:

  • 汉明距离适用于二进制值。前九个值似乎是 16 个十六进制数字,很容易解释为 64 位二进制值。我们知道如何使用它。然后你说“仅适用于整数”......这是真的,因为我们可以将 64 位二进制值表示为 BIGINT。然后您说您的要求是“和字母”[原文如此],并且您显示包含 'v''g' 的值,这些不是有效的十六进制数字. 塑料中有什么? 在回答您的问题之前,您需要解释一下 95gfgdgd75425456 应该代表什么二进制值。
  • 对不起,你没有理解问题。简而言之,我有哈希值,是的,它们是存储在 mysql 中的十六进制十进制数。只是想将它与我正在发送的内容进行比较,这可以通过 bit_count 来完成,但我听说它只适用于整数。所以如果我通常使用 SELECT pagedata,BIT_COUNT(pagecontent^'$encrypted')searchengine WHERE pagecontent > 2 ; ”),我主要怀疑它是否以字母数字形式工作?这让我怀疑比特计数的替代品。我只从这里得到它的整数工作:stackoverflow.com/questions/4777070/…
  • 我理解了这个问题。我不明白字符串 74898acvdf56655695gfgdgd7542545 应该代表什么二进制值。 (这些是十六个字符,大部分字符是有效的十六进制数字,但是字符 vg无效十六进制数字。)至于您的“主要怀疑它是否以字母数字形式工作”...... ,它不起作用。汉明距离适用于 二进制 值。将十六进制字符串表示转换为二进制很容易...
  • 我不明白您打算如何处理包含无效十六进制数字字符的“字母数字”字符串。将 16 个十六进制字符转换为 64 位二进制并不难CONVERT(CONV('ffe71b001820a1fd',16,10),UNSIGNED) 参考:CONV() functionCONVERT() function
  • 好吧,其实 74898acvdf566556 和 95gfgdgd7542545 打错了,分别是 74898fababfbef46 和 95efabfeba752545,意思是十六进制

标签: php mysql hash hamming-distance


【解决方案1】:

以最后两个数字为例:

SELECT BIT_COUNT( CAST(CONV('fffa181c1c3e3820', 16, 10) AS UNSIGNED) ^
                  CAST(CONV('fffa381c1c3e3828', 16, 10) AS UNSIGNED) ) ;
--> 2
  • 哈希是十六进制的。
  • 转换需要以BIGINT UNSIGNED 结束。

(如果您有 MD5(128 位)或 SHA1(160 位)哈希,我们将不得不通过 SUBSTR() 对它们进行拆分,对每对进行异或 BIT_COUNT,然后将结果相加。)

编辑以使用列名:

SELECT BIT_COUNT( CAST(CONV( a.pagecontent , 16, 10) AS UNSIGNED) ^
                  CAST(CONV( b.pagecontent , 16, 10) AS UNSIGNED) ) ;

【讨论】:

  • 好吧,但主要问题是将客户端数据与服务器端哈希匹配,您的解决方案是针对客户端的(意味着在 fecthig 之前更改)但是已经存储在 mysql 中的情况如何,如何更改?
  • @125fura:“如何改变那个”(其中“那个”是指存储在 MySQL 表的列中的值)取决于列,以及二进制值如何表示。 (列CHAR(16) 是否包含十六进制数字,或者列定义为VARCHAR(21) 并包含'qw 4 fffa181c3c2e3920',如您的问题所示。您需要使用的确切表达式取决于如何二进制哈希值在列中表示。
  • 请提供SHOW CREATE TABLE
  • @spencer7593,数据存储为 varchar(16) 和 qw,4 是名称和编号。这不是强制性的。
  • 对于使用超过 64 位的任何人,请谨慎。这行不通,至少不是“原样”。您需要将十六进制分成 16 位组,BIT_COUNT 每个^,然后将 bit_counts 相加。
猜你喜欢
  • 1970-01-01
  • 2017-09-10
  • 2017-04-03
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 2011-06-14
  • 2015-03-21
相关资源
最近更新 更多