Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can result of BobJenkinsHash function be negative?

Environment: Win7 64bit, Delphi 2010, Win32 project.

I try to get integer hash values for set of strings with the help of BobJenkinsHash() function from Generics.Defaults.

It works but some points are not clear for me.

  1. Can result of the function be negative?

As I see on source site it is used uint32_t as result type of the hashword() function:

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 */
{

Is it unsigned int?

  1. Second question is I have different results for different strings with identical values:

    'DEFPROD001' => 759009858
    'DEFPROD001' => 1185633302
    

Is it normal behaviour?

My full function to calculate hash (if first argument is empty then second is returned):

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;
like image 721
mad Avatar asked Mar 12 '23 06:03

mad


1 Answers

The Delphi implementation is declared like so:

function BobJenkinsHash(const Data; Len, InitData: Integer): Integer;

It returns a signed 32 bit integer. So yes, this implementation can return negative values.

The C implementation you refer to returns an unsigned 32 bit integer. So that cannot return negative values.

Assuming both implementations are correct then they will, given the same input, return the same 32 bits of output. It's just that when interpreted as signed or unsigned values these bits have different meaning.

As to your second question, passing the same string to the hash function will yield the same hash. You must have made a mistake in your test case.

BobJenkinsHash(defaultID, Length(defaultID) * SizeOf(defaultID), 0);

Here defaultID is a string variable and that is implemented as a pointer. You are therefore hashing the address. And not even doing that correctly due to your incorrect length argument. Instead you need to write:

BobJenkinsHash(Pointer(defaultID)^, Length(defaultID) * SizeOf(Char), 0);

This program demonstrates:

{$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.

Output:

2129045826
-331457644
-161666357
-161666357
like image 122
David Heffernan Avatar answered Mar 19 '23 16:03

David Heffernan