Convert Double to Integer for GetHashCode in Delphi

Delphi 2009 added the GetHashCode function to TObject. GetHashCode returns an integer that is used for hashing in a TDictionary.

If you want the object to work well in TDictionary, you need to override GetHashCode accordingly so that in general different objects return different integer hash codes.

But what do you do for objects containing double fields? How do you turn these double values ​​into integers for GetHashCode?

As is usually done in Java, let's say use the Double.doubleToLongBits or Float.floatToIntBits method. The latter has documentation that describes it as follows: "Returns a representation of the specified floating point value in accordance with the IEEE 754 single format floating point bit format." This is due to some bitwise operations with different masks for different bits of the floating point value.

Is there a function that does this in Delphi?

+3
source share
5 answers

I suggest the following improvement over Gamecat code:

type
  TVarRec = record
    case Integer of
      0: ( FInt1, FInt2 : Integer; )
      1: ( FDouble : Double; )
  end;

function Convert(const ADouble: Double): Integer;
var
  arec : TVarRec;
begin
  arec.FDouble := ADouble;
  Result := arec.FInt1 xor arec.FInt2;
end;

This takes into account all bits of the double value.

(comments do not work with code)

+5
source

double , :

type
  TVarRec = record
    case Integer of
      0: ( FInt : Integer; )
      1: ( FDouble : Double; )
  end;


function Convert(const ADouble: Double): Integer;
var
  arec : TVarRec;
begin
  arec.FDouble := ADouble;
  Result := arec.FInt;
end;

, .

( , :

function Convert(const ADouble: Double): Integer;
var
  tempDouble : Double;
  tempInt    : Integer absolute tempDouble; // tempInt is at the same memory position as tempDouble.
begin
  tempDouble := ADouble;
  Result := tempInt;
end;
+2

- , GetHashCode , : . , , , .

, , Double 3.5, , - 12345678. - , , , 5,21. , -, - 23456789, .

, , , GetHashCode , . ( , .)

0

, Java- Delphi :

type
  TVarRec = record
    case Integer of
      0: ( FInt1: Integer; )
      1: ( FSingle: Single; )
  end;

function GetHashCode(Value: Double): Integer;
var
  arec: TVarRec;
begin
  arec.FSingle := Value;
  Result := arec.FInt1;
end;

, (Sizeof (Single) = Sizeof (Integer)). , -.

: D2009, .

0

Use CRC32 for Double data because xor is evil.

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TVarRec = record
    case Integer of
      0: ( FInt1, FInt2 : Integer; );
      1: ( FDouble : Double; );
  end;

function Convert(const ADouble: Double): Integer;
var
  arec : TVarRec;
begin
  arec.FDouble := ADouble;
  Result := arec.FInt1 xor arec.FInt2;
end;

var
  FDoubleVar1, FDoubleVar2: TVarRec;
  HashCode1, HashCode2: Integer;
begin
  // Make a Double
  FDoubleVar1.FInt1 := $DEADC0DE;
  FDoubleVar1.FInt2 := $0C0DEF00;

  // Make another Double
  FDoubleVar2.FInt1 := $0C0DEF00;
  FDoubleVar2.FInt2 := $DEADC0DE;

  WriteLn('1rst Double   : ', FDoubleVar1.FDouble);
  WriteLn('2nd Double    : ', FDoubleVar2.FDouble);

  HashCode1 := Convert(FDoubleVar1.FDouble);
  HashCode2 := Convert(FDoubleVar2.FDouble);

  WriteLn('1rst HashCode : ', HashCode1);
  WriteLn('2nd HashCode  : ', HashCode2);

  if HashCode1 = HashCode2 then
  begin
    WriteLn('Warning: Same HashCode!');
  end;
  ReadLn;
end.
0
source

Source: https://habr.com/ru/post/1715332/


All Articles