Probleme mit Fix64

  • 1
  • 2
  • 3
  • 4
  • 5
  • Page 3 of 5
mc-electronic
Benutzer
Avatar
Gender: n/a
Location: Sauerland NRW
Posts: 372
Registered: 03 / 2008
Subject:

Re: Probleme mit Fix64

 · 
Posted: 17.04.2013 - 17:36  ·  #17
Hi Rolf, hello Avra,

using Fix64 quite a while now, I found the following problem: The Source for "FloatToFix64" above and the build in function in the compiler give erratic results when working with very small negative values:

The code

Var
lFl1 : Float;
..
Begin
lFl1 := -0.00000000001;
SLIP_WriteStr('TXT|lFl1: '+FloatToStr(lFl1));
SLIP_WriteStr('TXT|FloatToFix64(lFl1): '+Fix64ToStr(FloatToFix64(lFl1)) );
...
End;


Will give the following result:

lFl1: -9.999992E-12
FloatToFix64(lFl1): -1.000000000

The FloatToFix64 conversion gives -1 !! I checked, it is not the Fix64ToStr Function. So, all calculation with very small negative Values, that are converted from FloatToFix64 go wrong.

Can you have a look? If you fix the issue, I would be glad, if you could post the corrected code for FloatToFix64 here, so I can prevent the "uses uFix64" clause (making my code too big)

Hope you can help!

Thanks, Michael
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 17.04.2013 - 21:56  ·  #18
Hello Michael,

I'm afraid I can't help you there.
I think Avra is the right one for this.

rolf
mc-electronic
Benutzer
Avatar
Gender: n/a
Location: Sauerland NRW
Posts: 372
Registered: 03 / 2008
Subject:

Re: Probleme mit Fix64

 · 
Posted: 18.04.2013 - 05:35  ·  #19
Hi Rolf,

Yes, I think you are right. I did some testing and now I have changed the Function a little bit to prevent the false -1 results. However, Avra should have a look, because the internal AVRco routine in uFix64 gives the erratic results too..

Cheers, Michael

function FloatToFix64(const a: float): fix64;
var
Tmp: TFix64Overlay;
begin
If (a > -0.0000000009) And (a < 0) Then
a := 0;
EndIf;
Tmp.i := Trunc(a);
if (a < 0) and (Frac(a) <> 0) then
Dec(Tmp.i);
endif;
Tmp.f := Trunc(Frac(a) * (float($FFFFFFFF) + 1));
return(Tmp.fix);
end;
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 18.04.2013 - 07:48  ·  #20
I will take a look.
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 18.04.2013 - 13:14  ·  #21
Hello Avra,
here a code snippet which shows the problem:
Code
var
  f                    : float;
  f64                  : fix64;
  
type
  TFix64Overlay = record
                    fix : fix64;
                    i [@fix+4]: longint;
                    f [@fix] : longword;
                  end;

function FloatToFix64(const a: float): fix64;
var
  Tmp: TFix64Overlay;
begin
  Tmp.i := Trunc(a);
  if (a < 0) and (Frac(a) <> 0) then
    Dec(Tmp.i);
  endif;
  Tmp.f := Trunc(Frac(a) * (float($FFFFFFFF) + 1));
  return(Tmp.fix);
end;

procedure FixTest;
begin
  f:= -0.00000000001;
  f64:= FloatToFix64(f);
end;

rolf
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 20.04.2013 - 17:22  ·  #22
Hello Michael,

because the smallest number in Fix64 can be +/-0.000000001 your entry of -0.00000000001
exceeds the possible Fix64 range. The FloatToFix64 function doesn't recpgnize this.
But you can change this by an additional check in this function.
Maybe Avra has a more elegant way for this...
rolf
Code
function FloatToFix64(const a: float): fix64;
var
  Tmp: TFix64Overlay;
begin
  if a = 0.0 then
    return(0.0);
  elsif abs(a) < 0.000000001 then
    if sign(a) then
      return(0.000000001);
    else
      return(-0.000000001);
    endif;
  endif;
  Tmp.i := Trunc(a);
  if (a < 0) and (Frac(a) <> 0) then
    Dec(Tmp.i);
  endif;
  Tmp.f := Trunc(Frac(a) * (float($FFFFFFFF) + 1));
  return(Tmp.fix);
end;
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 21.04.2013 - 00:32  ·  #23
Hello Rolf,

Your solution is in the right direction, but it has a slight error if a=0. This should be the real fix:

Code
function FloatToFix64(const a: float): fix64;
var
  Tmp: TFix64Overlay;
begin
  if ValueInRange(a, -2.328307E-10, 0) then
    Tmp.fix := 0;
  else
    Tmp.i := Trunc(a);
    if (a < 0) and (Frac(a) <> 0) then
      Dec(Tmp.i);
    endif;
    Tmp.f := Trunc(Frac(a) * (float($FFFFFFFF) + 1));
  endif;
  return(Tmp.fix);
end;

I will send you the corrected unit once I return to my hometown.

Michael, Thank you for noticing this bug!
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 21.04.2013 - 00:37  ·  #24
Hello Avra,

thank you. But I'm missing the positive overflow.
And a zro return can be very dangerous. It should be the smallest Fix64 number
so that, for example, a later division by zero can not happen.

rolf
  • 1
  • 2
  • 3
  • 4
  • 5
  • Page 3 of 5
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   131   145 · Page-Gen-Time: 0.024731s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI