mikrocontroller.net

Forum: Compiler & IDEs Konvertierung Kommazahl->Fixed-Point-Format durch Precompiler ungenau!?


Autor: krischi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

für mein Projekt benutze ich eine kleine selbst geschriebene Fixed-Point 
Bibliothek um Berechnungen im Format s15.16 durchführen zu können. 
Bisher dachte ich eigentlich, dass diese gut funktionieren würde, doch 
heute ist mir per Zufall aufgefallen, dass der Precompiler vorgegebene 
Werte teilweise recht ungenau konvertiert. Zur Konvertierung nutze 
folgende Typendefinition und ein entsprechendes Makro:
typedef s15_16_t       int32_t

#define floatToFix(f)  ((s15_16_t)( (f) * (1<<16) ))

Wenn ich nun z.B. 693,0983 konvertieren möchte und das durch den 
AVRStudio Simulator jage, liefert mir dieser als Ergebnis 0x02B5192C 
bzw. dezimal 45422892. Wenn ich das nun aber per Hand ausrechne bekomme 
ich 693,0983 * 65536 = 45422890,1888. Nach Abschneiden der 
Nachkommastellen ergibt das allerdings eine Differenz von 2! Obwohl es 
mir logisch erscheinen würde, dass der Precompiler ebenfalls die Stellen 
abschneidet, gebe es selbst im Fall dass er aufrundet immer noch einen 
Unterschied von 1!

Wie ist dieses Verhalten zu erklären? Prinzipiell sollte eine einfache 
Multiplikation von zwei solch gutmütigen Zahlen (beide in etwa in der 
gleichen Größenordnung) doch nicht derartig ungenau sein! Kann jemand 
dieses Verhalten reproduzieren oder hab ich vielleicht irgendwo anders 
einen Fehler?

Achja, das ganze habe ich mit dem neuesten WinAVR-20090313 kompiliert.

Vielen Dank im voraus!

Gruß, krischi

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der AVR-GCC hat nur das einfache float Format und kein double.
D.h. die Mantisse hat nur eine Genauigkeit von 23 Bit.

Deine Zahl ist aber deutlich größer als 23 Bit und daher muß der Fehler 
>1 sein.


Peter

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
krischi schrieb:

> Wie ist dieses Verhalten zu erklären? Prinzipiell sollte eine einfache
> Multiplikation von zwei solch gutmütigen Zahlen (beide in etwa in der
> gleichen Größenordnung) doch nicht derartig ungenau sein!

Nebenbei: Bei Multiplikation und Division von Fliesskommazahlen spielt 
es überhaupt keine Rolle, ob die Operanden in der gleichen 
Grössenordnung liegen oder extrem auseinander. Das ist nur bei Addition 
und Subtraktion relevant.

Autor: krischi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, vielen Dank! Das erklärt das natürlich. In die Richtung habe ich 
schon gedacht, aber wie man sieht habe ich von float nicht wirklich viel 
Ahnung. Das werde ich gleich mal als Anlass nehmen, um mich etwas 
intensiver mit der Thematik zu beschäftigen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt übrigens keinen `precompiler'.

Es gibt nur einen Präprozessor (bzw. mittlerweile `preprocessing'
genannt, da es selbst beim GCC kein separat gestarteter Prozess
mehr ist), aber der macht nur dumme Makroersetzung.  Die Berechnung
von zur Compilezeit konstanten Ausdrücken obliegt dem Compiler
selbst.

Autor: Ollz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die Berechnung von zur Compilezeit konstanten Ausdrücken obliegt dem
> Compiler selbst.

Mit dem kleinen Sonderfall, dass der GCC Preprozessor konstante 
Integer-Ausdrücke in Bedingungen (#if) ebenfalls ausrechnet um die 
Bedingung zu prüfen. Dabei rechnet er mit dem grössten Integer-Typ den 
er hat.

Verwendet man den gleichen Ausdruck im eigentlichen Code, kann nach 
Expansion (durch den Preprozessor) und dann Berechnung durch den 
Compiler bei dieser Berechnung was anderes rauskommen, als das, was der 
Preprozessor sich in einer Bedingung ausgerechnet hat. Sehr lustig :-(

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.