【问题标题】:MSSQL BIT_COUNT (Hammingdistance)MSSQL BIT_COUNT(汉明距离)
【发布时间】:2014-01-28 01:41:43
【问题描述】:

MSSQL中有没有类似MYSQLBIT_COUNT函数的函数?我想在 MSSQL 中创建一个非常简单的 Hammingdistance 函数,我可以在我的选择中使用它。

这是我为 MYSQL 准备的:

CREATE FUNCTION `HAMMINGDISTANCE`(`hasha` BIGINT, `hashb` BIGINT)
    RETURNS int(11)
    DETERMINISTIC
    RETURN 
    BIT_COUNT(hasha^hashb)

【问题讨论】:

  • 使用 SQL CLR。必须是Hamming 吗? Levenshtein 怎么样,有很多可用的示例。例如。 levenshtein.blogspot.com
  • 我需要汉明来通过生成的感知散列比较图像。我会试试 SQL CLR,谢谢。 :)
  • @Remus Rusanu - 如果他只需要计算位数,他为什么还需要 SQL CLR?详情请参阅我的回答。
  • @dcp:因为 CLR 将围绕 T-SQL 代码计数位运行循环
  • @Remus Rusanu - 您是否对它进行了基准测试以找出答案?我不太相信。

标签: mysql sql sql-server


【解决方案1】:

为什么不在 T-SQL 中编写您自己的 bit_count 代码?如果您只需要计算 bigint 中设置的位数,则无需使用 SQL CLR。这是一个例子:

CREATE FUNCTION bit_count
(
   @pX bigint
)
RETURNS int
AS
BEGIN
   DECLARE @lRet integer
   SET @lRet = 0
   WHILE (@pX != 0)
   BEGIN
      SET @lRet = @lRet + (@pX & 1)
      SET @pX = @pX / 2
   END   
   return @lRet   
END
GO

另外,这里有一个fiddle,你可以试试看这个函数的实际效果。

请注意,此算法仅适用于非负 bigint。如果您正在寻找一种适用于负 bigint 的算法,请参阅 this link

【讨论】:

  • 这个函数的输入 hasha^hashb 怎么样? SQL Server doesn't supportbigint 之间的按位运算。
  • 他的问题是如何进行 bit_count,但您提出了一个好问题。胡萝卜运算符在 MySQL 中究竟做了什么?我认为它是异或,但似乎并非如此,因为 XOR 是 MySQL 异或运算符 (dev.mysql.com/doc/refman/5.0/en/…)。我用谷歌搜索了 MYSQL 胡萝卜运算符,但没有得到任何点击,所以我很困惑。你知道那个接线员是做什么的吗?
  • 我也想过异或。但实际上在测试bigint 确实 似乎毕竟工作。在线书籍只提到int/tinyint/smallint,但DECLARE @B BIGINT = 9223372036854775807;SELECT @B ^ 0 实际上似乎工作正常。
  • @Martin - 是的,好点,它似乎确实适用于 bigints。我刚刚尝试过,它也给出了正确的结果:选择 cast(9223372036854775807 as bigint) ^ cast(123421349333 as bigint)。但是,我仍然不确定胡萝卜运算符是独占还是在 MySQL 中,因为我找不到任何文档。
  • carrot 运算符应该在 mysql 中执行此操作,因为这是我多年前编写时所期望的...但无论如何它有效,所以我猜它这样做了。
【解决方案2】:

我刚刚使用 dcp 提供的代码编写了一个 HAMMINGDISTANCE,它似乎可以工作。

CREATE FUNCTION [dbo].[HAMMINGDISTANCE](@hasha BIGINT, @hashb BIGINT)
    RETURNS int
AS
BEGIN
   DECLARE @pX BIGINT
   DECLARE @lRet integer
   SET @lRet = 0
   SET @pX = @hasha ^ @hashb
   WHILE (@pX != 0)
   BEGIN
      SET @lRet = @lRet + (@pX & 1)
      SET @pX = @pX / 2
   END   
   return @lRet   
END

GO

【讨论】:

  • 很高兴它有效,但请注意我使用的算法不适用于负数。如果您需要算法,请查看我的编辑。
【解决方案3】:
CREATE FUNCTION [dbo].[fn_hamming_distance]
(
    @a     BIGINT,
    @b     BIGINT
)
RETURNS TINYINT
AS
BEGIN
    DECLARE @c BIGINT = @a ^ @b
    RETURN 
    CASE 
         WHEN @c IS NULL
              THEN NULL
         ELSE CASE 
                   WHEN @c < 0 THEN 1
                   ELSE 0
              END
              +
              CASE 
                   WHEN @c & 0x4000000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x2000000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x1000000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x800000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x400000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x200000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x100000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x80000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x40000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x20000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x10000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x8000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x4000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x2000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x1000000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x800000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x400000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x200000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x100000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x80000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x40000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x20000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x10000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x8000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x4000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x2000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x1000000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x800000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x400000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x200000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x100000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x80000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x40000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x20000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x10000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x8000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x4000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x2000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x1000000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x800000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x400000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x200000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x100000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x80000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x40000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x20000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x10000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x8000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x4000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x2000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x1000 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x800 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x400 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x200 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x100 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x80 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x40 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x20 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x10 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x8 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x4 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x2 > 0 THEN 1
               ELSE 0
          END
          +
          CASE 
               WHEN @c & 0x1 > 0 THEN 1
               ELSE 0
          END
    END
END

【讨论】:

  • 感谢您的回答。考虑添加解释如何解决提问者的问题。
猜你喜欢
  • 1970-01-01
  • 2017-09-10
  • 2015-03-21
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
相关资源
最近更新 更多