13

Is simple way to convert double value to its bytes representation? I tried using pointers like:

var
  double_v:double;
  address:^double;
....
double_v:=100;
address:=@double_v;

but every my concepts: how to read thise 8 bytes from address, end with "AV".

3 Answers 3

16

Use a variant record

Type
  TDoubleAndBytes = Record
    case boolean of
      false : (dabDouble : Double);
      true  : (dabBytes : Array [0..7] Of Byte);
  end;

Assign the double value to dabDouble and read the bytes through dabBytes

var
  myVar : TDoubleAndBytes;
  i : integer;

begin
  myVar.dabDouble := 100;
  for i:=0 to 7 do write(myVar.dabBytes[i]);
Sign up to request clarification or add additional context in comments.

15 Comments

Impossibly fast and helpful reply! Thank you very much.
To be sure that the variant parts overlap, you should always use a packed record for these purposes. In this case it doesn't make a difference (so you were lucky), but in general, this trick only works with packed records.
@Rudy: It is not necessary in this case but as a rule of thumb, you're right.
@Rudy That's poor advice. Each variant in the variant part of the record will start at the same address, even if the containing variant record is aligned. Making a record packed is a disaster for alignment and performance. Doing it here would put a double away from an 8 byte boundary. Which will lead to runtime failure for SSE code. For example, x64 floating point. The key, and this is not well understood in my experience, is that packed affects both internal layout, and overall alignment.
@DavidHeffernan: Can I test this with a core i7 and BDS 2006? A simple test works (packed record filler : byte; case boolean...)
|
11

In XE3 there are record helpers for simple types, TDoubleHelper.

This works:

var
  d : Double;
  i : Integer;
begin
  d := 100.0;
  for i := 0 to 7 do
    WriteLn(d.Bytes[i]);
end;

In XE2 there is a declaration TDoubleRec, which is an advanced record.

example:

var
  dRec : TDoubleRec;
  i : Integer;
begin
  dRec := 100.0;
  for i := 0 to 7 do
    WriteLn(dRec.Bytes[i]);
end;

Another common option to access the bytes of a double is to use a typecast:

type
  TDoubleAsByteArr = array[0..7] of byte;
var
  d : Double;
  i : Integer;
begin
  d := 100.0;
  for i := 0 to 7 do
    WriteLn(TDoubleAsByteArr(d)[i]);
end;

1 Comment

+1 I don't use XE, but it's interesting to know that delphi improves.
7

Two examples for using of "absolute" ...

Used as function

function GetDoubleByte(MyDouble: Double; Index: Byte): Byte;
var
  Bytes: array[0..7] of Byte absolute MyDouble;
begin
  Result := Bytes[Index];
end;



procedure TForm1.Button1Click(Sender: TObject);
var
 MyDouble:Double;
 DoubleBytes:Array[0..7] of Byte absolute MyDouble; // direct local use
begin
  MyDouble := 17.123;
  ShowMessage(IntToStr(DoubleBytes[0])); // local usage

  ShowMessage(IntToStr(GetDoubleByte(MyDouble,0))); // via function call

end;

1 Comment

Thank You. All Yours proposals opened my eyes for newer (in my life) appearance of Delphi.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.