mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Warum funktioniert float->char Konvertierung nicht korrekt ?


Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,

ich brauche für mein µC - Projekt eine Möglichkeit float->char* zu 
konvertieren. In der stdio.h gibt es ja z.B. sprintf, was aber mein C30 
Compliler nicht bietet.

Es ist ja auch egal. Ich habe mir selbst ein Programm geschrieben, 
welches mir die Konvertierung für beliebig viele Stellen macht.

Allerdings funktioniert es nicht immer korrekt. Wenn ich 0,015 in char 
konvertiere, bekomme ich '0'',''0''1''4''9''9' heraus ? Viele andere 
Zahlen gehen wieder wunderbar. Es gibt eben einige Ausnahme, wie z.B. 
0,015 oder 0,01.

Vielleicht weiß jemand die Ursache ?


Hier der Code:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;

int main(void)
{
     float f=0.015;       //zu konvertierende float Zahl
     int i=0;
     int j=0;
     int k=0;
     int NO=1;  
       
     char c[10];
     
     if(f<0)                   //Vorzeichenkontrolle
     {      c[i]='-';
            f*=-1;
            i++;
     }
     else
     {
         c[i]='+';
         i++;
     }
     
     while(1)                 //Zerlegung
     {
       if(f/10.0<1.0)
       {
          c[i]=(int)f%10+48;   //Offset von 48 - ASCII
          i++;
          for(j=0;j<9;j++)     //Komma bereits gesetzt ?
          {
             if(c[j]=='.') NO=0;
          }
          if(NO && k==0)
          {
          c[i]='.';
          i++;
          }
          if(k!=0)
          k--;
          
          f=f-((int)f%10);
          f*=10;
       }
       
       else 
       {
       f/=10.0;
       k++;
       }
       
       if(i==8) break;
     }                  
     
     char* str = &c[0];
     cout<<"\n"<<c[0]<<c[1]<<c[2]<<c[3]<<c[4]<<c[5]<<c[6]<<c[7];
     
     cin>>f;
     return 0;
}

Ich bin keiner, der effiziente Algorithmen programmiert, aber mein Code 
funktioniert meistens :) Also bitte nicht aufregen, wenn ich es zu 
umständlich mache oder den Wald vor lauter Bäumen übersehe.

MfG
Frank

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in float lässt sich leider eine 0.015 nicht darstellen, dein µC hat nach 
der zuweisung eine 0.0.14999999999999 gespeichert. Musst also auf die 
anzahl stellen runden die du ausgeben willst. Das ganze ist ein 
generelles Problem mit float.

Autor: lkmiller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>...in float lässt sich leider eine 0.015 nicht darstellen...

Wenn ich sowas in MSVC++ schreibe:
   float flt1=0.014999999;
   float flt2=0.015;

   printf("%f  %f",flt1, flt2);

dann kommt heraus:
  0.01500  0.01500

Wie denn dann das?

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

Bewertung
0 lesenswert
nicht lesenswert
lkmiller wrote:
>>...in float lässt sich leider eine 0.015 nicht darstellen...
>
> Wenn ich sowas in MSVC++ schreibe:
>
>    float flt1=0.014999999;
>    float flt2=0.015;
> 
>    printf("%f  %f",flt1, flt2);
> 
>
> dann kommt heraus:
>   0.01500  0.01500
>
> Wie denn dann das?

Weil printf bei der Ausgabe selbst rundet.

Probier mal:

   printf("%.6f  %.6f",flt1, flt2);

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na klasse.

Gibt es eine Funktion, die unmittelbar floats runden kann ?
Also man gibt die Anzahl der Stellen vor ?

Danke für eure Beiträge.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wird wohl schlecht gehen, wenn die funktion wieder float zurückliefert 
hast du das gleiche wie vorher.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast recht.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und wenn du es in int wandelst?

also die round(0.014999999 * 10000000) und dann hast du 150000 - wenn du 
die ausgabe eh selber machst braucht du bloss noch das komma richtig zu 
setzten

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter wrote:
> und wenn du es in int wandelst?
>
> also die round(0.014999999 * 10000000) und dann hast du 150000 - wenn du
> die ausgabe eh selber machst braucht du bloss noch das komma richtig zu
> setzten

Bei mir ergibt das 149999,99 und als int umgewandelt 149999

Autor: Hans Wurst (hans_wurst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist echt komisch.

Kann eigentlich jemand erklären warum man mit float keine 0.015 
darstellen kann? Ist doch schließlich eine Zahl wie jede andere.

Danke für Antworten.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das round() war mit absicht drin

das Problem ist das binäre zahlensystem.
Im Dezimalen System kann man auch nicht 1/3 genau darstellen.

Finde jetzt leider keien gute Erklärung aber hier sind mehr Infos
http://de.wikipedia.org/wiki/IEEE_754

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter wrote:
> das round() war mit absicht drin

Und was macht round? Runden auf wieviel Stellen? Jaja... Oder meinst 
du damit, dass die Nachkommastellen korrekt gerundet werden?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also das round sollte auf INT runden, also auf 0 stellen

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.