Konvertierung Kommazahl->Fixed-Point-Format durch Precompiler ungenau!?

Gast #1371752
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:
1
typedef s15_16_t       int32_t
2

3
#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
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.
Gast
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.
Moderator Persönliche Seite
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.
Gast
> 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

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.