2016-04-09 12 views
-2

So habe ich dieses Programm, in dem ich brauche Werte in 0.0x Bereich zu vergleichen und wenn ich zum Beispiel scannen 50.21 mit diesem kleinen DingWert der Schwimmer unterscheidet sich von dem, was gescannt wurde

scanf("%f",bill); 

der Wert gespeichert in var. Rechnung ist eigentlich 50.2099990845 ... was später im Programm Berechnungen zunichte macht. Gibt es eine Möglichkeit, diese Nummer in 50.210000 zu verwandeln? Vielen Dank für Ihre Zeit.

+1

Nein, aus dem üblichen Grund. 50.21 ist nicht genau darstellbar. Vielleicht können Sie Festkommaarithmetik verwenden? – harold

+1

Ich nehme an, Sie meinten 'scanf ("% f ", &bill);', mit dem Adressenoperator? Oder ist 'bill' ein Zeiger? –

+2

Sie wissen, wie' 1/3' als Dezimalzahl mit einem Punkt dargestellt ist 0,333. .. 'geht für immer weiter? Nun,' 1/10', dargestellt als binär mit einem Punkt, macht dasselbe - wie '1/100' Dies ist ein Problem, wenn Werte, die als exakte Dezimalzahlen dargestellt werden, in binäre Fließkommawerte umgewandelt werden sind spezielle Fälle, in denen es funktioniert (ganze Zahlen, Vielfache von 0,5 oder 0,25 oder 0,125 usw.), aber im Allgemeinen kann es nicht gemacht werden, Sie müssen die nächste Annäherung akzeptieren, die zu der binären Gleitkommadarstellung passt used. – Steve314

Antwort

0

Verwenden IEEE-754 Floating-Zahlen nicht (single, float, double) für dezimale Berechnungen, bei denen alle Stellen gleichermaßen von Bedeutung sind (soweit geschäfts Regeln betroffen sind). Dies liegt daran, dass IEEE-754 Rundungsfehler aufweist und einige triviale Dezimalzahlen nicht genau darstellen kann. Es ist wirklich für wissenschaftliche und technische Anwendungen gedacht, bei denen geringe Informationsverluste akzeptabel sind.

Wenn es sich um Dezimalzahlen mit fester Genauigkeit handelt (z. B. Währungswerte), empfiehlt es sich, vorgemischte Ganzzahlen zu verwenden, sodass 100 (für 100 Cent) 1 Dollar darstellt.

Wenn du gehst scanf zu verwenden, empfehle ich folgendes:

int dollars = 0, cents = 0; 
bool done = false; 
while(!done) { 
    done = scanf("%4d.%2d", &dollars, &cents) != 2 
} 

cents += dollars * 100; 

Hinweis meine Verwendung der maximalen Länge Bezeich (4 und 2 jeweils) einen Puffer-Überlauf in scanf zu verhindern.

+0

Ich wünschte, diese Idee strich mich, bevor ich den gesamten Code schrieb rund um float ...: D – Erik

+0

'... scanf ("% 4d.% 2d ", & Dollar, & Cent)! = 2 ... Cent + = Dollar * 100; 'scheitert, wenn' Dollar <0 '. Besser: 'Cent = Dollar * 100 + Zeichen (Dollar) * Cent;' – chux

0

Floats in C (und den meisten anderen Sprachen) werden als IEEE-754 Darstellungen gespeichert. Sie können sich diese als Basis-Zwei-Approximationen von Zahlen in wissenschaftlicher Notation vorstellen.

In Ihrem Fall kann 50.21 nicht exakt im Binärformat dargestellt werden, da .21 kein Vielfaches von 2 ist, also macht die Software ihr Bestes, indem sie auf 50.2099990845 gerundet wird.

Für Finanzanwendungen sollten Sie besser eine ganze Zahl mit dem Betrag in Cent speichern, nicht in Dollar (oder gleichwertig). Auf diese Weise werden Sie keine Rundungsfehler auf dem Weg haben!

Verwandte Themen