AVR-GCC und GCC Unterschiedliche Rechnung?

#1610143
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
#1610193
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.
#1610333
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.
#1610507
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
#1610528
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...
Moderator Persönliche Seite #1610547
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.
#1610696
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
Moderator Persönliche Seite #1610770
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren