BobJenkinsHash函数的结果可能是否定的?

mad*_*mad 4 delphi string hash

环境:Win7 64bit,Delphi 2010,Win32项目.

我尝试在Generics.Defaults的BobJenkinsHash()函数的帮助下获取字符串集的整数哈希值.

它有效,但有些观点对我来说并不清楚.

  1. 功能结果可能是否定的?

正如我在源站点上看到的那样 ,它使用uint32_t作为hashword()函数的结果类型:

uint32_t hashword(
const uint32_t *k,                   /* the key, an array of uint32_t values  */
size_t          length,               /* the length of the key, in uint32_ts    */
uint32_t        initval)         /* the previous hash, or an arbitrary value */
{
Run Code Online (Sandbox Code Playgroud)

它是unsigned int吗?

  1. 第二个问题是我对具有相同值的不同字符串有不同的结果:

    'DEFPROD001' => 759009858
    'DEFPROD001' => 1185633302
    
    Run Code Online (Sandbox Code Playgroud)

这是正常的行为吗?

我的全部函数来计算哈希值(如果第一个参数为空则返回第二个):

function TAmWriterJD.ComposeID(const defaultID: string; const GUID: String): String;
var
  bjh: Integer;
begin
  if defaultID = '' then
  begin
    Result := GUID
  end
  else
  begin
    bjh := BobJenkinsHash(defaultID, Length(defaultID) * SizeOf(defaultID), 0);
    Result := IntToStr(bjh);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 7

Delphi实现声明如下:

function BobJenkinsHash(const Data; Len, InitData: Integer): Integer;
Run Code Online (Sandbox Code Playgroud)

它返回一个带符号的32位整数.所以是的,这个实现可以返回负值.

您引用的C实现返回无符号的32位整数.这样就无法返回负值.

假设两个实现都是正确的,那么在给定相同输入的情况下,它们将返回相同的32位输出.只是当解释为有符号或无符号值时,这些位具有不同的含义.

至于你的第二个问题,将相同的字符串传递给散列函数将产生相同的散列.你必须在测试用例中犯了一个错误.

BobJenkinsHash(defaultID, Length(defaultID) * SizeOf(defaultID), 0);
Run Code Online (Sandbox Code Playgroud)

defaultID是一个string变量,它实现为指针.因此,您正在对地址进行哈希处理.由于你的长度参数不正确,甚至没有正确地做到这一点.相反,你需要写:

BobJenkinsHash(Pointer(defaultID)^, Length(defaultID) * SizeOf(Char), 0);
Run Code Online (Sandbox Code Playgroud)

该计划表明:

{$APPTYPE CONSOLE}

uses
  System.Generics.Defaults;

var
  s, t: string;

begin
  s := 'DEFPROD001';
  t := 'DEFPROD001';

  Writeln(BobJenkinsHash(s, Length(s) * SizeOf(s), 0));
  Writeln(BobJenkinsHash(t, Length(t) * SizeOf(t), 0));

  Writeln(BobJenkinsHash(Pointer(s)^, Length(s) * SizeOf(Char), 0));
  Writeln(BobJenkinsHash(Pointer(t)^, Length(t) * SizeOf(Char), 0));

  Readln;
end.
Run Code Online (Sandbox Code Playgroud)

输出:

2129045826
-331457644
-161666357
-161666357

  • `abs`是一个非常糟糕的主意,因为它只会使用32位中的31位来使你的哈希函数表现不佳.此外它会失败,因为abs(MININT)超出范围.简单地将哈希重新解释为"红衣主教".用`Cardinal(inthash)` (2认同)