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


von Daniel R. (zerrome)


Lesenswert?

Hallo,
Folgender Code Schnipsel produziert unterschiedliche Zahlen. Auf dem Pc 
mit GCC korrekt und auf dem AVR mit AVG-GCC falsch. Aber wieso?
1
  unsigned char rfreq[9];
2
  unsigned char i;
3
4
  for(i=0;i<9;i++)rfreq[i]=0;
5
6
  rfreq[4]=2;
7
  rfreq[3]=168;
8
  rfreq[2]=108;
9
  rfreq[1]=224;
10
  rfreq[0]=36;
11
12
13
  unsigned long long tmp;
14
  double dbl=0;
15
16
  void *vptr;
17
  vptr=&rfreq[0];
18
19
  tmp=*(unsigned long long*)vptr;
20
  dbl+=tmp;
21
  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

von g457 (Gast)


Lesenswert?

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

HTH

von Klaus (Gast)


Lesenswert?

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

von Rolf M. (rmagnus)


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.

von Klaus W. (mfgkw)


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?

von Karl H. (kbuchegg)


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.

von (prx) A. K. (prx)


Lesenswert?

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

von Daniel R. (zerrome)


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

von (prx) A. K. (prx)


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...

von Daniel R. (zerrome)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Klaus W. (mfgkw)


Lesenswert?

Ansonsten Festkommazahlen.

von Falk B. (falk)


Lesenswert?


von Daniel R. (zerrome)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.