Makaku00
Makaku00

Reputation: 121

Converting float or negative integer to hexadecimal in Borland Delphi

Ive written a program that communicate with some hardware using a serial connection. It sends a lot of hexadecimal values my way (sensor readings) and every once in a while it sends a negative value. ex. i receive a hexadecimal value : FFFFF5D6 and i have to convert it into : -2602

another problem i have is that i can't convert a float into hex and back.

Are there any simple ways of doing this?

Upvotes: 1

Views: 6327

Answers (4)

ventiseis
ventiseis

Reputation: 3099

If you want to separate the exponent and the significand, you can use a variant record:

  TExtRec = packed record
    case Boolean of
      false:
        (AValue: Extended);
      true:
        (ASignificand: uint64; ASignExp: uint16;)
  end;

I think this helps to understand the structure of the floating point number.

Example usage:

var
  r: TExtRec;
begin
  r.AValue := 123.567;
  ShowMessage(IntToHex(r.ASignExp) + IntToHex(r.ASignificand));
end;

Output:

 4005F7224DD2F1A9FBE7

You can calculate it back:

v = (-1)s * 2(e-16383) * (i.f)

With

  • e = $4005 = 16389 and
  • i.f = $F7224DD2F1A9FBE7
  • i.f = 1.930734374999999999954029827886614611998084001243114471435546875
  • v=123.566999999999999997057908984743335167877376079559326171875

To convert i.f, i've used a binary converter.

Upvotes: 0

skamradt
skamradt

Reputation: 15538

You can "convert" from hex to float by using an integer large enough to cover the float value used, then using the ABSOLUTE keyword. All that is really doing is encoding the memory of the value as an integer. Be very careful to use types which are exactly the same size (you can use SIZEOF to find the memory size of a value). If you need an odd size, then absolute against an array of byte and loop through and convert to/from each byte (which would be two characters hex).

the ABSOLUTE keyword forces two variables to START at the same memory address, any value written from one is immediately available in the other.

var
  fDecimal : Double; // size = 8 bytes
  fInteger : Int64 absolute fDecimal;  // size = 8 bytes
begin
  fDecimal := 3.14;
  ShowMessage(format('%x=%f',[fInteger,fDecimal]));
  fInteger := StrToInt64('$1234123412341234');
  ShowMessage(FloatToStr(fDecimal)+'='+Format('%x',[fInteger]));
end;

here is the routine for floats with odd sizes:

var
  fDecimal : extended;
  fInteger : array[1..10] of byte absolute fDecimal;
  sHex     : string;
  iX       : integer;
begin
  ShowMessage(IntToStr(SizeOf(fDecimal))+':'+IntToStr(SizeOf(fInteger)));
  fDecimal := 3.14;
  sHex := '';
  for iX := 1 to 10 do
    sHex := sHex + IntToHex(fInteger[iX],2);
  ShowMessage(sHex);
  // clear the value
  fDecimal := 0.0;
  // Reload the value
  for iX := 1 to (Length(sHex) DIV 2) do
    fInteger[iX] := StrToInt('$'+Copy(sHex,(Ix*2)-1,2));
  ShowMessage(FloatToStr(fDecimal));
end;

Upvotes: 2

RRUZ
RRUZ

Reputation: 136391

to convert a hex string into a integer, you can use the StrToInt Function , also you can check the TryStrToInt function (wich returns False if string does not represent a valid number).

uses
SysUtils;

var
ivalue : integer;
begin
ivalue:=StrToInt('$FFFFF5D6'); // Hexadecimal values start with a '$' in Delphi

..
end;

For the Hexadecimal representation of a float number, you can check theses articles.

Upvotes: 1

EricLaw
EricLaw

Reputation: 57075

I've never seen a float represented in hex, so you'd have to figure out exactly what format the device is using for that. For the negative number case, you'll need to use HexToInt to covert it to an integer, and then determine if that integer is larger than whatever threshold value represents MaxInt for the hardware's integer data type. If it's bigger than that, it's a negative number, which means you'll need to, IIRC, get the number's 1s complement and convert it to negative.

Upvotes: 0

Related Questions