Forum: Mikrocontroller und Digitale Elektronik Float formatieren ohne printf


von Werner (Gast)


Lesenswert?

Hallo,

ich versuche mir grade eine einfache Umwandlung für floats zu bauen:
1
    double f = 0.245;
2
    
3
    while (f) {
4
        f = f * 10;
5
        int temp = f;
6
        printf("%d", temp);
7
        f = f - temp;
8
    }

Problem ist aufgrund der Eigenart von floats, dass als Ergebnis

245000000000000017763568394002504646778106689453125

herauskommt.

Wie löst printf das Problem?

von Wolfgang (Gast)


Lesenswert?

Werner schrieb:
> Problem ist aufgrund der Eigenart von floats, dass als Ergebnis
>
> 245000000000000017763568394002504646778106689453125

Viel spannender finde ich die Frage, wie du eine derartige Zahl in eine 
Variable vom Datentyp int reinbekommen hast. Wenn ich mich nicht 
verzählt habe, bräuchtest du dafür ein int mit mindestens 168 Bit.
Das kommt mir - mit Verlaub - etwas exotisch vor.

von Wolfgang (Gast)


Lesenswert?

p.s. Ein Double kommt auf 15..16 gültige Stellen. Alles andere entsprint 
der Lückenhaftigkeit der mit Double darstellbaren Zahlenmenge.

von (prx) A. K. (prx)


Lesenswert?

Wolfgang schrieb:
> Viel spannender finde ich die Frage, wie du eine derartige Zahl in eine
> Variable vom Datentyp int reinbekommen hast.

Wo hat er das?

von Bernd K. (prof7bit)


Lesenswert?

Wolfgang schrieb:
> Viel spannender finde ich die Frage, wie du eine derartige Zahl in eine
> Variable vom Datentyp int reinbekommen hast

Nein. Er hat nur kein newline drin. Er gibt immer den ganzzahl-wert aus, 
subtrahiert den und multipliziert den Rest mit 10 für die nächste 
stelle. Er will es in einen String umwandeln.

von (prx) A. K. (prx)


Lesenswert?

Werner schrieb:
> Wie löst printf das Problem?

Basisfunktionen dafür können fcvt/gcvt/ecvt sein:
http://sydney.edu.au/engineering/it/~kev/pp/RESOURCES/cplusplus/ref/cstdlib/fcvt.html
Sourcecode wird sich finden lassen.

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


Lesenswert?

Werner schrieb:
> Wie löst printf das Problem?

Schau dir doch den Sourcecode an. ;-)

von Murmelchen (Gast)


Lesenswert?

Moin,

das 'Problem' ist hier weder temp noch printf, das Problem ist die 
Schleife und deren Abbruchbedingung. Die Schleife läuft schlicht durch, 
weil die Abbruchbedingung, so wie Du sie haben möchtest, aufgrund der 
zwangsläufigen Rundungsfehler bei Fließkommazahlen nicht (immer) exakt 
erfasst wird.

Daher nimmt man dafür am besten auch entweder gar keinen float oder 
double, oder wenn doch, dann prüft man auf einen kleinen von Null 
verschiedenen Wert, wenn Null das Ziel des Abbruchs sein soll.

Und die einzelnen Ziffern werden, wie schon erwähnt wurde, als eine 
Zeile ausgegeben, weil Newline \n in printf fehlt.


C ist eine sehr schöne Programmiersprache, mit der man sich auf jede nur 
erdenkliche Art ins Knie schießen kann.


Mit besten Grüßen

Murmelchen

von PittyJ (Gast)


Lesenswert?

Ein bisschen Theorie gibt es unter:
https://de.wikipedia.org/wiki/IEEE_754

von Peter D. (peda)


Lesenswert?

Schreib 100 mal an die Tafel:
"Man darf float nie auf Gleichheit testen!"

Die einzigen Ausnahmen sind INFINITY und NAN.

von Stefan F. (Gast)


Lesenswert?

> "Man darf float nie auf Gleichheit testen!"

Yes, YMMD.

von Werner (Gast)


Lesenswert?

>Schreib 100 mal an die Tafel:
>"Man darf float nie auf Gleichheit testen!"

Wenn man kurz darüber nachdenkt: 1000 mal!
Warum macht eigentlich ein Compiler keine Warnung bei sowas?

Das hier war der geeignete Fingerzeig:

>Basisfunktionen dafür können fcvt/gcvt/ecvt sein:

http://www.jbox.dk/sanos/source/lib/fcvt.c.html

In meinem Fall kann ich fcvt_r nehmen, wegen Eintrittsinvarianz...

Vielen Dank!

Werner

von Stefan F. (Gast)


Lesenswert?

Tut er doch, wenn du alle Warnungen aktivierst (was ich per default in 
neuen Projekten immer mache).

-Wfloat-equal
    Warn if floating-point values are used in equality comparisons.

    The idea behind this is that sometimes it is convenient (for the 
programmer) to consider floating-point values as approximations to 
infinitely precise real numbers. If you are doing this, then you need to 
compute (by analyzing the code, or in some other way) the maximum or 
likely maximum error that the computation introduces, and allow for it 
when performing comparisons (and when producing output, but that's a 
different problem). In particular, instead of testing for equality, you 
should check to see whether the two values have ranges that overlap; and 
this is done with the relational operators, so equality comparisons are 
probably mistaken.

von Werner (Gast)


Lesenswert?

Sollte das nicht in -Wall eingeschlossen sein?

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


Lesenswert?

Peter D. schrieb:
> Die einzigen Ausnahmen sind INFINITY und NAN.

0 ebenfalls, aber nur, wenn sie aus einer Zuweisung kommt, nicht aus
einer Rechnung.  (Die 0 ist eindeutig dargestellt dann.)

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.