webentwicklung-frage-antwort-db.com.de

iOS Objective-C Wie erhalte ich einen nach dem Komma gerundeten Gleitkommawert?

Ich habe ein

float a = 1412.244019;

und ich muss auf die nächste zweite Dezimalstelle wie 1412.24000000 gerundet werden. Ich verstehe, dass, wenn ich ein mit nur zwei Dezimalstellen präsentieren möchte, ich% .2f verwende, aber das ist NICHT der Fall. Ich brauche das neue a aus mathematischen Gründen als Schwimmer.

Ich habe ein paar Methoden ausprobiert, die beim Stackoverflow ohne Glück gefunden wurden. Das offensichtliche, das ich benutzte, erwähne ich unten, aber hatte noch kein Glück, es zu benutzen. Kannst du sehen, warum die Magie nicht geschieht?

PS: Es bewirkt manchmal den gewünschten Effekt, NICHT immer, was mich zum Nachdenken bringt ... hmmm ...

Danke im Voraus.

Code:

float a = 1412.244019;
NSLog(@"a is %f", a); //output a is 1412.244019
a = [[NSString stringWithFormat:@"%.2f", a] floatValue];
NSLog(@"a is %f", a); //output a is 1412.239990

EDIT:

Scheint, als ob ich den Schwimmer nach der obigen Operation benutze, erachtet er es als 1412.240000, obwohl das NSLog etwas anderes sagt ... seltsam. Aber ich bekomme, was ich will, also ein dickes Lob für die verschwendete Zeit nichts zu jagen :)

EDIT Ich würde euch gerne alle als richtige Antworten auswählen, aber da ich nur eine auswählen kann, habe ich die erste gute Antwort mit zusätzlicher Erklärung (der beiden) ausgewählt zuletzt).

29
B-Man

Hast du das versucht?

CGFloat val = 37.777779;

CGFloat rounded_down = floorf(val * 100) / 100;   /* Result: 37.77 */
CGFloat nearest = floorf(val * 100 + 0.5) / 100;  /* Result: 37.78 */
CGFloat rounded_up = ceilf(val * 100) / 100;      /* Result: 37.78 */

source: Rundungszahl auf 2 Dezimalstellen in C

Ergänzung: Sie haben nur keine Kontrolle darüber, wie der Computer den Gleitkommawert speichert.

Diese gerundeten Werte sind also möglicherweise nicht GENAU die "offensichtlichen" Dezimalwerte, aber sie liegen sehr nahe beieinander, und das ist die maximale Garantie, die Sie haben werden.

58
Lucas Eduardo

Sie tun dies in Objective-C genauso wie in C:

double notRounded = ...;
double rounded = round (notRounded * 100.0) / 100.0;

Verwenden Sie float nicht - es sei denn, Sie können jemandem genau erklären, warum Sie float over double verwenden. Schwimmer hat eine sehr begrenzte Präzision. Und die Verwendung von Decke oder Boden ist dumm, da es eine perfekte Standardfunktion gibt, die als "rund" bezeichnet wird.

Weder float noch double können gena die meisten Dezimalwerte darstellen, wie z. B. 12.24. Da es eine viel höhere Präzision hat, können Sie mit double näher an 12.24 heranrücken. Daher besteht eine große Chance, dass NSLog eine seltsame Zahl für (float) 12.24 anzeigt, wie 12.23999997394 oder was auch immer, während es 12.24 für double anzeigt.

11
gnasher729

Fehler in dieser Zeile

a = [[NSString stringWithFormat:@"%.2f", a] floatValue];

korrigiere es zu

a = [NSString stringWithFormat:@"%.02f", a];
6
Mitesh Varu

Der nächste Wert für 1412.24, den ein float haben kann, ist 1412.239990234375. Es gibt eine no - Operation, die ein float erzeugen kann, da das Format von float -Objekten keine näheren Werte darstellt. Die Aufforderung, 1412.24 in float darzustellen, entspricht der Aufforderung, 2.5 in int darzustellen. Das geht einfach nicht.

Optionen für den Umgang damit sind:

  • Sie können eine Formatierung verwenden, die "1412.24" anzeigt, ohne das zugrunde liegende Objekt float zu ändern.
  • Sie können double verwenden, um näher zu kommen (viel näher), aber es wird immer noch nicht genau 1412.24 sein.
  • Sie können float Werte auf darstellbare Werte skalieren (z. B. in anderen Einheiten messen, sodass die gewünschten Werte in float alle genau darstellbar sind).
  • Sie können einen anderen Datentyp verwenden, z. B. NSDecimal.
5

Sie können keinen Float-Wert erzwingen. Floats sind eher ungefähre Werte, da ihre Größe sehr groß sein kann. Da Sie nur so viele Bits verwenden können, kann sie nahe an eine Dezimalzahl heranreichen, diese aber nicht exakt ausdrücken.

Ein Vorschlag ist, alle Ihre Arithmetik in Ganzzahl, multipliziert mit 100, und dann zu teilen, wenn Sie Ihr Endergebnis anzeigen möchten. Möglicherweise sind die Zahlen zu groß, um dies zu verhindern.

2
Owen Hartnett

Sie können a mit 100,0 multiplizieren und zum Runden 0,5 addieren und dann den int-Wert des Ergebnisses nehmen. Anschließend können Sie mit/100 den Wert vor dem Dezimalpunkt und mit% 100 die beiden Dezimalstellen abrufen.

2
David Elliman