www.mikrocontroller.net

Forum: Compiler & IDEs AVR-GCC und GCC Unterschiedliche Rechnung?


Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Folgender Code Schnipsel produziert unterschiedliche Zahlen. Auf dem Pc 
mit GCC korrekt und auf dem AVR mit AVG-GCC falsch. Aber wieso?
  unsigned char rfreq[9];
  unsigned char i;

  for(i=0;i<9;i++)rfreq[i]=0;

  rfreq[4]=2;
  rfreq[3]=168;
  rfreq[2]=108;
  rfreq[1]=224;
  rfreq[0]=36;


  unsigned long long tmp;
  double dbl=0;

  void *vptr;
  vptr=&rfreq[0];

  tmp=*(unsigned long long*)vptr;
  dbl+=tmp;
  dbl/=(unsigned long long) 268435456;


Ist jetzt zwar ziemlich gehackt aber sollte doch laufen?!?
Richtiges Ergebnis wäre ungefähr 42,52658094465732574463

Auf dem Pc schau ich mir das ganze mit : "printf("Zahl: %f\n",dbl);" an 
und auf dem Controller mit: "lcd_puts( dtostre(dbl,conv_str,31,0x04) 
);". Die Variable conv_str ist 100 Byte lang, nur zur Sicherheit...


Ich verstehs nicht. Bitte Hilfe :)

Grüße Daniel

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne zu wissen auf welchen Architekturen Du das getestet hast und ohne 
die Zeigerarithmetik nachgeprüft zu haben: Ich tippe auf Endianness.

HTH

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie groß ist denn ein unsigned long long in den beiden Fällen?
Und stimmt die endianess in beiden Fällen überein?

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel R. schrieb:
> Auf dem Pc mit GCC korrekt und auf dem AVR mit AVG-GCC falsch.

g457 schrieb:
> Ohne zu wissen auf welchen Architekturen Du das getestet hast und ohne
> die Zeigerarithmetik nachgeprüft zu haben: Ich tippe auf Endianness.


> Ist jetzt zwar ziemlich gehackt aber sollte doch laufen?!?

Ein Grund könnte sein, daß double auf dem AVR 32 Bit breit ist.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe es auch nicht.
Wieso ist z.B. rfreq 9 Elemente groß?

Ansonsten sehe ich das auch so, daß du von 8-Byte-double ausgehst, was 
bei AVR falsch ist.

Wer nicht weiß, was er macht und wie die interne Darstellung aussieht,
sollte vielleicht etwas defensiver programmieren?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel R. schrieb:

> Auf dem Pc schau ich mir das ganze mit : "printf("Zahl: %f\n",dbl);" an
> und auf dem Controller mit: "lcd_puts( dtostre(dbl,conv_str,31,0x04)
> );".

Das ist zwar nett, aber höchst wahrscheinlich sinnlos um dem Problem auf 
die Spur zu kommen.
Du willst dein Byte-Array als unsigned long long einsetzen. Also 
solltest du dir als Allererstes ansehen, ob die Interpretation der Bytes 
als unsigned long long auf dem AVR mit der auf dem PC übereinstimmt. 
Wenn die schon nicht übereinstimmt (Stichworte wurde ja schon genannt: 
Endianess, unterschiedliche Datentyplängen), darfst du dich nicht 
wundern, wenn danach nichts mehr stimmt.

> Ich verstehs nicht. Bitte Hilfe :)
Binäre Übertragung von Zahlen kann tricky sein. Will man diesen 
Problemen aus dem Weg gehen, dann einigt man sich auf den absolut 
kleinsten Nenner: Zahlen werden in textform übertragen. Neben Problem 
mit der Endianess und unterschiedlichen Darstellungen (bei float/double) 
hat das dann auch noch den Nebeneffekt, das Protokollsynchronisierung 
viel einfacher ist.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Byteorder (Endianess) stimmt überein, aber die Länge nicht.

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
danke für die Tips.
Hintergrund des Codes ist, dass ich mit einem AVR die Register eines 
SI570 über TWI auslese und jetzt die Berechnung der neuen Registerwerte 
vornehmen will, dazu brauche ich mindestens 38 Bit Gnauigkeit.
Das double nur 4 Byte lang ist wusste ich nicht, finde ich auch seltsam. 
Wie lang ist denn dann ein Float? Wo stehen denn die Datentypen in der 
avr-libc? Gibt es im c99 Mode denn dann 8 Byte long double?
Mit der Endianess war ich mir eigentlich auch sicher, dass die bei 
beiden Plattformen übereinstimmt. Einmal mein Notebook mit Linux x86 gcc 
und beim Atmega168 mit avr-gcc.

Grüße Daniel

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel R. schrieb:

> Das double nur 4 Byte lang ist wusste ich nicht, finde ich auch seltsam.

Ist nicht konform mit dem Standard, wurde aber der Einfachheit halber so 
implementiert. Es gibt beim avr-gcc keine 64-Bit Fliesskommarechnung.

Wenn dir also 64-Bit Integers nicht ausreichen...

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Es gibt beim avr-gcc keine 64-Bit Fliesskommarechnung.

Hm schade, dann muss ich wohl doch mehr programmieren als ich vorhatte 
:)
Nun gut.
Danke an alle.

Viele Grüße

Daniel

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

Bewertung
0 lesenswert
nicht lesenswert
Daniel R. schrieb:
> Hintergrund des Codes ist, dass ich mit einem AVR die Register eines
> SI570 über TWI auslese und jetzt die Berechnung der neuen Registerwerte
> vornehmen will, dazu brauche ich mindestens 38 Bit Gnauigkeit.

Lass mal die Kirche im Dorf.  Mit einer 32-bit-Gleitkommazahl erreichst
du eine Genauigkeit von 6...7 Dezimalstellen, also besser als 1E-6.
Der Si570 hat eine Genauigkeit von 1.5E-6, und das bereits ohne
Berücksichtigung von Temperatureinflüssen.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ansonsten Festkommazahlen.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ja Festkommaarithmetik steht jetzt auf dem Programm, ist wahrscheinlich 
eh schneller und evtl. je nach Aufwand genauer als mit 32 Bit Fließkomma 
zu rechnen.

@Jörg Wunsch
Du sprichst die 1.5 ppm Initial Accuracy an die im Datenblatt angegeben 
ist, richtig?
Der Si570 wird mit Heizung in Metallgehäuse betrieben und mit einem 
Frequenznormal Kalibriert, das sollte dann besser als 1.5 ppm werden, 
denke ich mal wobei 1.5 ppm schon nicht schlecht ist :)
Im Datenblatt steht das man mit 38 Bit rechnen soll...

Grüße Daniel

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

Bewertung
0 lesenswert
nicht lesenswert
Daniel R. schrieb:

> ja Festkommaarithmetik steht jetzt auf dem Programm, ist wahrscheinlich
> eh schneller

Ich glaube, das ist ein Trugschluss.

> und evtl. je nach Aufwand genauer als mit 32 Bit Fließkomma
> zu rechnen.

Ob sie genauer wird, hängt u. a. davon mit ab, ob du mehrere Dekaden
überstreichen musst oder nur einen engen Bereich.  Ein Vorteil der
Gleitkommazahlen ist halt, ungefähr die gleiche Genauigkeit über
viele Zehnerpotenzen Gesamtgröße zu bieten.

> Du sprichst die 1.5 ppm Initial Accuracy an die im Datenblatt angegeben
> ist, richtig?

Ja.

> Der Si570 wird mit Heizung in Metallgehäuse betrieben und mit einem
> Frequenznormal Kalibriert, das sollte dann besser als 1.5 ppm werden,
> denke ich mal wobei 1.5 ppm schon nicht schlecht ist :)

Naja, die Langzeitstabilität war ja auch noch einmal eine Größen-
ordnung schlechter angegeben, und Temperatureinflüsse hatte ich
sowieso nicht berücksichtigt.

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.