[fpc-pascal] TFloatHelper.BuildUp() question

Bart bartjunk64 at gmail.com
Fri Dec 15 13:36:29 CET 2017


Hi,

I think I misunderstand what this procedure is for?

Procedure BuildUp(const ASignFlag: Boolean; const AMantissa: QWord;
const AExponent: Integer);

>From it's signature I would expect that it constructs a float from the
supplied parameters.
I also assumed that this would be reciprocal: if I query Sign,
Mantissa and Exponent from a given float, then uses BuildUp with these
parameters, I would get a float with the original value back:

This however seems not to be the case.

======================
program fl;
{$mode objfpc}
{$h+}

uses
  SysUtils;

const
  Signs: Array[Boolean] of Char = ('+','-');

  function DbgS(E: Extended): String; overload;
  begin
    Result := 'Sign: ' + Signs[E.Sign] +
              ' Mantissa: ' + IntToHex(E.Mantissa, SizeOf(E.Mantissa)*2) +
              ' Exp: ' + IntToHex(E.Exp, SizeOf(E.Exp)*2) +
              ' Frac: ' + IntToHex(E.Frac, SizeOf(E.Frac)*2);
  end;

function DbgS(D: Double): String; overload;
begin
  Result := 'Sign: ' + Signs[D.Sign] +
            ' Mantissa: ' + IntToHex(D.Mantissa, SizeOf(D.Mantissa)*2) +
            ' Exp: ' + IntToHex(D.Exp, SizeOf(D.Exp)*2) +
            ' Frac: ' + IntToHex(D.Frac, SizeOf(D.Frac)*2);
end;

function DbgS(S: Single): String; overload;
begin
  Result := 'Sign: ' + Signs[S.Sign] +
            ' Mantissa: ' + IntToHex(S.Mantissa, SizeOf(S.Mantissa)*2) +
            ' Exp: ' + IntToHex(S.Exp, SizeOf(S.Exp)*2) +
            ' Frac: ' + IntToHex(S.Frac, SizeOf(S.Frac)*2);
end;


var
  E: Extended;
  ESign, SSign, DSign: Boolean;
  EMant, EExp, EFrac, SMant, SExp, SFrac, DMant, DExp, DFrac: QWord;
  S: Single;
  D: Double;
begin
  writeln('Extended (',SizeOf(Extended),' bytes)');
  E := 1.0;
  writeln('E = ',E,#32,DbgS(E));
  ESign := E.Sign;
  EMant := E.Mantissa;
  EExp := E.Exp;
  EFrac := E.Frac;
  E.BuildUp(ESign, EMant, EExp);
  writeln('E = ',E,#32,DbgS(E));
  writeln;

  writeln('Double (',SizeOf(Double),' bytes)');
  D := 1.0;
  writeln('D = ',D,#32,DbgS(D));
  DSign := D.Sign;
  DMant := D.Mantissa;
  DExp := D.Exp;
  DFrac := D.Frac;
  D.BuildUp(DSign, DMant, DExp);
  writeln('D = ',E,#32,DbgS(D));
  writeln;

  writeln('Single (',SizeOf(Single),' bytes)');
  S := 1.0;
  writeln('S = ',S,#32,DbgS(S));
  SSign := S.Sign;
  SMant := S.Mantissa;
  SExp := S.Exp;
  SFrac := S.Frac;
  S.BuildUp(SSign, SMant, SExp);
  writeln('S = ',S,#32,DbgS(S));
  writeln;


end.
===========================

Output (tested with 3.0.4 and trunk):

Extended (10 bytes)
E =  1.00000000000000000000E+0000 Sign: + Mantissa: 0000000000000000
Exp: 0000000000003FFF Frac: 8000000000000000
E = Nan Sign: + Mantissa: 0000000000000000 Exp: 00000000000043FE Frac:
0000000000000000

Double (8 bytes)
D =  1.0000000000000000E+000 Sign: + Mantissa: 0000000000000000 Exp:
00000000000003FF Frac: 0010000000000000
D = Nan Sign: + Mantissa: 0000000000000000 Exp: 00000000000007FE Frac:
0010000000000000

Single (4 bytes)
S =  1.000000000E+00 Sign: + Mantissa: 0000000000000000 Exp:
000000000000007F Frac: 0000000008000000
S =  5.000000000E-01 Sign: + Mantissa: 0000000000000000 Exp:
000000000000007E Frac: 0000000008000000

What am I doing wrong here?

Bart



More information about the fpc-pascal mailing list