Forum: Mikrocontroller und Digitale Elektronik dtostrf ieee754 Ausgabefehler?


von Christian Z. (Gast)


Lesenswert?

Hallo

Ich versuche mich gerade in C-Programmierung und probiere z.Z. dtostrf 
und dtostre aus. Wenn ich den µC rechnen lasse und das Ergebnis auf den 
LCD ausgebe haut das ja hin:
1
  float f1 = -1.25;
2
  float f2 = 2.5;
3
  float f = f1 * f2;
4
  char s1[20];
5
  lcd_string(dtostrf (f,6,2,s1));  //Ausgabe z.B.: 123.34
6
  lcd_string(dtostre (f,s2,3,1));  //Ausgabe z.B.: 1.2334e+02

Das Ergebnis auf dem LCD lautet 3.125 und ist somit korrekt.

Im nächsten Schritt habe ich aus Wikipedia einen Gleitkommawert (Single 
Precision) nach IEEE754 als Hew _Wert eingegeben:

Zahl = +11,25 = 0b01000001001101000000000000000000 = 0x41340000

und wollte dann die korrekte Zahl auf dem LCD sehen aber raus kam:

1093926792,14

Der Codeschnipsel dazu:
1
  float f1 = 0x41340000
2
  char s1[20];
3
  lcd_string(dtostrf (f1,6,2,s1));  //Ausgabe z.B.: 123.34
4
  lcd_string(dtostre (f1,s1,3,1));  //Ausgabe z.B.: 1.2334e+02

Kann mir das bitte jemand erklären?

von Karl H. (kbuchegg)


Lesenswert?

Christian Z. wrote:

> Das Ergebnis auf dem LCD lautet 3.125 und ist somit korrekt.

Du hast noch viel zu lernen :-)

> Der Codeschnipsel dazu:
> [avrasm]
>   float f1 = 0x41340000

Äh, nein.
Damit setzt du nicht die Bitrepräsentierung auf 0x41340000
sondern du weist dem float die Zahl 1093926912 zu.

Das ist grundsätzlich nichts anderes, als wie wenn du
schreiben würdest:

   float f = 3;

um f den Wert 3 zu geben. Nur dass du deine Zahl als Hex-Zahl
formuliert hast.

> und wollte dann die korrekte Zahl auf dem LCD sehen aber raus kam:
1093926792,14

Zurück zu der Anmerkung von oben (von wegen lernen und so)

Du hast zugewiesen:              1093926912
und der float enthielt danach:   1093926792,14

Siehst du den Unterschied? Mit float erhältst du Fliesskommazahlen
die ca 6 bis 7 signifikante Stellen aufweisen. In deinem Fall
ist die 7-te Stelle (links zu zählen anfangen) sogar noch korrekt,
aber alles was rechts davon kommt, ist pure Erfindung (man kann
natürlich erklären warum das so ist, würde jetzt aber zu weit
führen). Und genau das meine ich mit: du musst noch viel lernen
wenn du im Zusammenhang mit float von korrekt sprichst. Diese
6 signifikanten Ziffern (die weniger werden wenn du dann auch noch
mit den floats rechnest), können einem nämlich den ganzen Tag
versauen. :-)

von Christian Z. (Gast)


Lesenswert?

Ersteinmal Danke für die schnelle Antwot zu so später Stunde!

Ja da oben habe ich noch das Minus vergessen, die Abneigung gegen das 
neg. Vorzeichen ist wohl in meinen Kontoauszügen zu suchen :)

Das zweite leuchtet mir ein, aber ich wußte mir nicht anders zu helfen. 
Kann ich das Bsp. aus Wikipedia, angenommen ich habe nur die Zahl im 
IEEE754 Format, denn mit dieser Funktion in der Form +11,25 ausgeben?

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


Lesenswert?

Hexadezimale Gleitkommazahlen kann man mit 0x1324p56 oder sowas
eingeben, aber ich bin mir mit der tatsächlichen Darstellung der
Bits im Moment nicht ganz sicher.  Probier sowas besser auf einem
Hostcomputer-C aus statt auf dem Controller.

von Karl H. (kbuchegg)


Lesenswert?

Ich würde mal die Umkehrung probieren:
float Zahl zuweisen und danach die Byte-Repräsentierung
begutachten. Wenn sie mit der Veröffentlichen übereinstimmt,
dann kann man das dann auch umgekehrt mache.
1
int main()
2
{
3
  union conv {
4
    float f;
5
    unsigned char b[4];
6
  } convert;
7
8
  convert.f = 11.25;
9
10
  for( int i = 0; i < 4; ++i )
11
    printf( "%x", convert.b[i] );
12
}

oder welche Möglichkeiten du auch immer hast um ein
Byte auszugeben.

von Christian Z. (Gast)


Lesenswert?

Ich habe mich jetzt erst mal demütig mit C Literatur eingedeckt.

Muss mir auch erst mal die Geschichte mit den Strukturen richtig zu 
Gemüte führen um zu verstehen was die union macht und C generell.
Ist es richtig das der float Wert als selbiger übergeben wird und dann 
Byteweise als char ausgelesen wird?

Ich habe das mal auf dem LCD ausgegeben und die Bytes sind zwar invers 
angeordnet aber es stimmt!!!

Mein Ziel ist es über RS485 Modbus RTU eine float Zahl im IEEE754 Format 
intern im µC weiterzuverarbeiten und wenn ich die Union wie 
vorgeschlagen umgekehrt laufen lasse müsste das ja passen...

Werde ich jetzt mal ausprobieren.

Auf jeden Fall vielen vielen Dank an Euch beide, werde dann mal meinen 
Fortschritt hier reinschreiben. Die Version mit der Eingabe in der Form 
0x1324p56 werde ich auch noch mal ausprobieren.

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.