环境:Win7 64位,Delphi 2010,Win32项目。
我尝试在Generics.Defaults的BobJenkinsHash()函数的帮助下获取字符串集的整数哈希值。
它有效,但有些观点对我来说并不清楚。
正如我所见 on source site使用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 */
{
是unsigned int吗?
第二个问题是我对具有相同值的不同字符串有不同的结果:
'DEFPROD001' => 759009858
'DEFPROD001' => 1185633302
这是正常行为吗?
我计算哈希的全部函数(如果第一个参数为空,则返回第二个):
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;
答案 0 :(得分:7)
Delphi实现声明如下:
function BobJenkinsHash(const Data; Len, InitData: Integer): Integer;
返回带符号的32位整数。所以,是的,这个实现可以返回负值。
您引用的C实现返回无符号的32位整数。所以这不能返回负值。
假设两个实现都是正确的,那么在给定相同输入的情况下,它们将返回相同的32位输出。只是当解释为有符号或无符号值时,这些位具有不同的含义。
关于第二个问题,将相同的字符串传递给散列函数将产生相同的散列。你必须在测试用例中犯了错误。
BobJenkinsHash(defaultID, Length(defaultID) * SizeOf(defaultID), 0);
此处defaultID
是string
变量,并作为指针实现。因此,您正在对地址进行哈希处理。由于你的长度参数不正确,甚至没有正确地做到这一点。相反,你需要写:
BobJenkinsHash(Pointer(defaultID)^, Length(defaultID) * SizeOf(Char), 0);
该计划证明:
{$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.
<强>输出:强>
2129045826 -331457644 -161666357 -161666357