Probleme mit Fix64

  • 1
  • 2
  • 3
  • 4
  • 5
  • Page 1 of 5
robert
Benutzer
Avatar
Gender: n/a
Location: Hildesheim / Deutschland
Posts: 249
Registered: 04 / 2006
Subject:

Probleme mit Fix64

 · 
Posted: 06.10.2010 - 14:19  ·  #1
Hallo,
mir sind zwei Dinge aufgefallen:
1. folgendes lässt sich nicht kompilieren, sondern liefert einen "Error: Pipe: type not supported":
Code
var
f  : fix64;
p : pipe[10] of fix64;
...
PipeSend(p, f);


2. Bei dem folgenden Beispiel rechnet er im Prozess teilweise ungenau. Er springt von 0.007 auf 0.00799999... Ich hätte vielleicht noch akzeptiert, dass er bei 0.007 + 0.001 IMMER ungenau rechnet, aber dem ist nicht so. Siehe Beispiel (nur im Simulator getestet).

Robert

Code
program bla;

Device = mega128, VCC=5;

Import
  SysTick,
  SerPort;

From System import
  Processes,
  Pipes,
  Fix64,
  longword;

from SysTick import
SystemTime32;

Define
  ProcClock      = 16000000;       {Hertz}
  SysTick        = 10;             {msec}
  StackSize      = $0100, iData;
  FrameSize      = $0100, iData;
  Scheduler      = 100, 100, iData;
  {----------------------------------------------------------------------------}
  SerPort        = 57600, Stop2;    {Baud, StopBits|Parity}
  RxBuffer       = 8, iData;
  TxBuffer       = 8, iData;


uses ;

Implementation

{$IDATA}

const

type
  tt = record
         f1 : fix64;
         f2 : fix64;
       end;

var
  t : tt;
  u : tt;
  pt: pipe[10] of tt;
  p : pipe[10] of fix64;
  f : Fix64;
  g : fix64;
  s : string[30];
  
process f_inc(100, 100 : iData);
begin
  t.f1 := t.f1 + 0.001;  //hier rechnet er teilweise ungenau
  repeat until (pipesend(pt, t));
end;

begin
  ENABLEINTS;
  WriteLn(SerOut, 'Los');
  f := 0.007;
  g := f + 0.001;       //hier rechnet er richtig
  s := Fix64ToStr(g);
  t.f1 := 0;
//  pipesend(p, f);    //Compiler Error
  loop
    if PipeStat(pt) > 0 then
      if PipeRecv(pt, u) then
        s := Fix64ToStr(u.f1);
        WriteLn(SerOut, s);
      endif;
    endif;
  endloop;
end bla.

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

Re: Probleme mit Fix64

 · 
Posted: 06.10.2010 - 16:41  ·  #2
Hallo Robert,

Pipes unterstützen keine 64bit Typen (Word64..Fix64) direkt. Da fehlte noch eine Compiler Fehlermeldung!
Man kann aber z.B. ein Fix64 in einen Record verpacken, dann sollte es tun:
Code
type
  f64rec = record
             f : fix64;
           end;
var
  p      : pipe of f64Rec;

=================================
So wie bei Float kann nicht jede Zahl absolut exakt dargestellt werden. Aber 0.0079999999 ist innerhalb der Genauigkeit von Fix64 = 0.008. Möglicherweise ist aber auch die Umwandlung in einen String zur Laufzeit hier die Ursache.
Ich denke User Avra kann hier mehr dazu sagen.

rolf
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: 06.10.2010 - 18:43  ·  #3
I will try to reply, but please correct me if I understood wrong, since online translation sometimes just sucks...

You should read this old thread first. I know it is for fix32 and not for fix64, but you will get the point. This is the main explanation extracted from it (the difference is just that with fix64 you have s31.32 numbers which means for fractional part you have 32 bits instead of 10 mentioned in the quote):
Quote
I am just not yet definitely sure about one thing, which is: should fixed point numbers use BINARY arithmetic for internal calculations or should they use BCD arithmetic. Let me explain... Till today I was strongly for using binary to have maximal use of available precision bits, and that is the way my lib is implemented - but if you take a look at the sample project you will see why I have (small) doubts. Let's take for an example s21.10 fixed point number. Having 10 bits for fractional part means that your minimal increment/decrement is 1/(2^10)=1/1024. It is clear that humans prefer 1/1000, and this means that some error is accumulated if for example you would like to add 0.001 thousand times to some fixed point number. If we would like to fix that, we would have to use BCD instead of binary, meaning that our range would then degrade from +-2^31.2^32 to probably +-10^7.10^8. I don't think that's acceptable and I think it's better to live with small accumulated error, but maybe there are some strong contra arguments that I am not aware of, so shoot... I am listening.

You could also take a look at both fix64 demos and see how to round printed fix64 numbers to 3rd decimal. That will solve your problem. Actually, since 0.001 is not actually 0.001 (actually it has very very small error discussed in quoted text), you could also round printed numbers to 9th decimal and get the same effect of getting 0.008 for 0.007 + 0.001.
robert
Benutzer
Avatar
Gender: n/a
Location: Hildesheim / Deutschland
Posts: 249
Registered: 04 / 2006
Subject:

Re: Probleme mit Fix64

 · 
Posted: 06.10.2010 - 20:28  ·  #4
@rolf
Der Trick mit dem Record ist mir bekannt. Mich hat die Compilermeldung gestört, weil ich die Pipe deklarieren, aber nicht benutzen kann.

@Avra
Thanks for the hints. Now it is clear. I usually use fixed numeric datatypes in sql programming. So I had in mind that the fix64 should be correct. My mistake.

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

Re: Probleme mit Fix64

 · 
Posted: 06.10.2010 - 20:35  ·  #5
Hello Robert,
Quote
So I had in mind that the fix64 should be correct

Fix64 is correct, in its mathematical limits. Please note that all Floats and Fix have their limitation. There are always numbers which can not absolutely exact represented.

rolf
robert
Benutzer
Avatar
Gender: n/a
Location: Hildesheim / Deutschland
Posts: 249
Registered: 04 / 2006
Subject:

Re: Probleme mit Fix64

 · 
Posted: 06.10.2010 - 20:41  ·  #6
Hello Rolf,
yes, it's clear now and I hope I will never forget this!

Robert
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: 07.10.2010 - 08:10  ·  #7
You were used to fixed point math in SQL/Delphi/C#... where BCD was used mostly for FIX128, but BCD is understandable when you have many GHz to spare. Fixed point math is usually there used for financial calculations (banks do not like errors accumulated after zillion transactions) which was another strong reason for BCD. In almost all embedded 32bit (like ARM), most 16bit (like some DSP) and all 8-bits, BCD is not used in fixed point numbers because of speed reasons. That same logic was used for this AVR implementation. In embedded systems fixed point math is used primary for huge speed improvement over floating point math. Compare speed of some complex function like SIN() between Fix64 number and Double floating point number (also 64 bits) and you will see a rabbit and a turtle. For example, this gives you just enough advantage with AvrCo to keep using AVR for some real time astronomy calculations, while AVR GCC user will have to switch to some ARM chip or make too many compromises which will make his product less competitive.
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Probleme mit Fix64

 · 
Posted: 07.10.2010 - 11:28  ·  #8
Hello Avra,

you mentioned AVR-GCC here. They claim to have doubles, but some people say this is simply float (32bit). Is this correct?

rolf
  • 1
  • 2
  • 3
  • 4
  • 5
  • Page 1 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: 10 · Cache Hits: 14   134   148 · Page-Gen-Time: 0.035015s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI