【问题标题】:T-SQL Hamming distance function capable of decimal / string / UInt64T-SQL Hamming 距离函数,支持十进制/字符串/UInt64
【发布时间】:2014-03-16 14:01:37
【问题描述】:

我需要将此 c# 函数转换为 T-SQL UDF

我需要从数据库中获取嗡嗡声距离小于 x 的所有行 此功能只是解决方案的一部分。

csharp 函数为这 2 个哈希返回 40,而 t-sql 函数返回 52

14714557628763197901

15383788748848265778

public static ulong csharp_hamming_distance(ulong hash1, ulong hash2)
{
ulong x = hash1 ^ hash2;
const ulong m1 = 0x5555555555555555UL;
const ulong m2 = 0x3333333333333333UL;
const ulong h01 = 0x0101010101010101UL;
ulong m4 = 0x0f0f0f0f0f0f0f0fUL;
x -= (x >> 1) & m1;
x = (x & m2) + ((x >> 2) & m2);
x = (x + (x >> 4)) & m4;
return (x * h01) >> 56;
}

我有样品,但结果不一样。

create function HammingDistance1(@value1 char(8000), @value2 char(8000))
returns int
as
begin
    declare @distance int
    declare @i int
    declare @len int

    select @distance = 0,
           @i =1,
           @len = case when len(@value1) > len(@value2)
                       then len(@value1)
                       else len(@value2) end

    if (@value1 is null) or (@value2 is null)
        return null

    while (@i <= @len)
        select @distance = @distance +
                           case 
                           when substring(@value1,@i,1) = substring(@value2,@i,1)
                                then 0
                           when substring(@value1,@i,1) < substring(@value2,@i,1)
                                then  CAST(substring(@value2,@i,1) as smallint) -  CAST(substring(@value1,@i,1) as smallint)
                           when substring(@value1,@i,1) > substring(@value2,@i,1)
                                then  CAST(substring(@value1,@i,1) as smallint) - CAST(substring(@value2,@i,1) as smallint)
                          else 1 end,
               @i = @i +1
    return @distance
end 

任何帮助将不胜感激

【问题讨论】:

  • 为什么不把它作为一个 CLR UDF,大概将值作为long(而不是ulong)传递并使用 -3732186444946353715 和 -3062955324861285838 作为输入?
  • 旁注:字符串汉明和二进制汉明是不同的;根据我的计算,这两个值之间的字符串汉明 as strings 是 18...你怎么得到 52?
  • 谢谢!!如果我不必运行这样的查询 SELECT Id FROM InstagramPhoto WHERE dbo.HamDist( convert(varchar,convert(decimal(32,0),phash)), convert(varchar,convert(decimal(32,0), 15383788748848265778))) stackoverflow.com/questions/4777070/…
  • 14714557628763197901 不适合bigint-3732186444946353715 只是相同位模式的有符号(而不是无符号)解释(注意:负数,因为设置了 MSB)。

标签: c# sql tsql user-defined-functions hamming-distance


【解决方案1】:

在汉明计算中,整数被视为位。汉明距离是比特差的数量,可以计算为两个值的异或中非零比特的数量。对于您提供的两个整数,按位汉明距离确实是 40。

14714557628763197901=
   1100110000110100100111000011001111001001011100011101000111001101

15383788748848265778=
   1101010101111110001100100101110000111010110000000111101000110010

^= 0001100101001010101011100110111111110011101100011010101111111111

这是 40 个非零位。显示的 C# 只是一种奇特的计数方式。

字符串不是这种情况。在 TSQL 中,您正在执行字符串汉明,传统上只是字符不同的位置数。对这两个值作为字符串执行经典汉明距离给出:

"14714557628763197901"
"15383788748848265778"
 01111111110111111111 = 18

您的示例 TSQL 代码正在执行修改后的汉明计算;要获得经典的汉明距离,只需删除最后两个 when 子句。

在 TSQL 中对 bigint 执行 二进制 汉明距离将非常困难,因为 TSQL 不支持对 bigint 的按位运算。但是,您可以使用整数运算分别对左右两半执行计算,然后将它们相加。唯一棘手的部分是该死的 MSB 和对变速的影响。

对小数执行汉明距离的定义不明确。您需要更具体地说明您认为这意味着什么。

【讨论】:

    猜你喜欢
    • 2016-08-09
    • 2021-08-30
    • 2018-08-31
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多