2013-08-05 2 views
23

Ich habe einiOS Objective-C Wie erhalten Sie 2 Dezimal gerundet Float-Wert?

float a = 1412.244019; 

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

Ich habe ein paar Methoden auf Stackoverflow ohne Glück versucht. Der offensichtlichste, den ich benutzte, erwähne ich unten, hatte aber immer noch kein Glück dabei. Kannst du sehen, warum die Magie nicht passiert?

PS: Es macht den manchmal gewünschten Effekt, nicht immer, was ich denken wird ... hmmm ...

Vielen Dank 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:

wie SCHEINT, wenn ich den Schwimmer einen nach der obigen Operation verwenden, es erwägt, es 1.412,240000 zu sein obwohl die NSLog anders sagt ... seltsam. Aber ich bin immer, was ich will, so Kudos für vergeudete Zeit nichts jagen :)

EDIT ich Sie alle richtigen Antworten lieben würde, zu wählen, aber da ich nur einen auswählen kann, wählte ich die erste gute Antwort mit extra Erklärung (der beiden letzten).

Antwort

49

Haben Sie 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 */ 

Quelle: Rounding Number to 2 Decimal Places in C

In Ergänzung: Sie haben gerade keine Kontrolle darüber, wie der Computer die Float-Wert speichert.

Also diese abgerundeten Werte möglicherweise nicht genau die "offensichtlichen" Dezimalwerte, aber sie werden sehr, sehr nahe sein, und das ist die maximale Garantie, die Sie haben werden.

+0

Haben Sie es versucht, Sah Sie diese Methode in einem anderen Beitrag gepostet. Aber der NSLog gibt immer noch die gleiche Antwort (versuchen Sie es selbst). Aber siehe oben EDIT. Obwohl der NSLog das "falsche" Format angibt, wird es korrekt verwendet. –

+0

Wie ich in der Bearbeitung gesagt habe, ist es unmöglich, volle Genauigkeit in Float-Punkten zu bekommen –

+0

Ich verstehe. Es berechnet es so, wie ich es möchte. Ich denke nur, dass das merkwürdig ist, weil Sie dann niemals genaue Arithmetik anwenden können? –

2

Sie könnten eine mit 100,0 multiplizieren und vielleicht 0,5 zum Runden hinzufügen und dann den int-Wert des Ergebnisses nehmen. Sie können dann/100 verwenden, um den Wert vor dem Dezimalpunkt zu erhalten, und% 100, um die zwei Dezimalstellen zu erhalten.

+0

Ich habe versucht, ohne Glück zu tun. Siehe Bearbeiten oben (in zwei Minuten) –

2

Sie können keinen Gleitkommawert erzwingen. Gleitkommazahlen sind so konstruiert, dass sie ungefähr angenähert sind, da ihre Größe sehr groß sein kann, und da Sie nur so viele Bits verwenden müssen, kann sie eine Dezimalzahl erreichen, aber nicht genau ausdrücken.

Ein Vorschlag besteht darin, alle Ihre Arithmetik in Ganzzahl, multipliziert mit 100, dann zu teilen, wenn Sie Ihr Endergebnis anzeigen möchten. Möglicherweise haben Sie zu große Nummern, die dies verbieten würden.

+0

Ich appreaciate deine Antwort, und ich denke, dass ich einen anderen Weg finden muss. Aber siehe oben EDIT. Obwohl der NSLog das "falsche" Format angibt, wird es korrekt verwendet. –

+0

NSLog sagt Ihnen die Wahrheit ... aber Sie verwenden wahrscheinlich andere Formatierung/Arithmetik, die ausbalanciert (wie Float-Arithmetik entwickelt wurde), um Sie in die Nähe der wahren Antwort zu bringen. Aber Sie werden feststellen, dass es manchmal das tut, was Sie erwarten, und manchmal hat es diese Nachkommastellen, die nicht da sein sollten, oder die Zahl ist nur kurz. Es ist am ausgeprägtesten, wenn Sie die Antwort drucken, oder wenn Sie versuchen, zwei Gleitkommazahlen zu vergleichen (d. H. 2.0! = 5.0 - 3.0). Wenn Sie genaue, genaue Arithmetik benötigen, um immer auf 2 Dezimalstellen zu liegen, sollten Sie Integer wie oben und/100 verwenden. –

5

Der nächste Wert von 1412.24, den ein float haben kann, ist 1412.239990234375. Es gibt keine Operation, die eine float näher als das, weil das Format float Objekte keine näheren Werte darstellen kann. Das Stellen von 1412.24 in float zu fragen ist, als würde man bitten, 2,5 in int darzustellen. Es kann einfach nicht gemacht werden.

Optionen mit diesem für den Umgang umfassen:

  • Sie können Verwendung Formatierung verwenden, die „1412,24“ zeigt, ohne das zugrunde liegende float Objekt 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 Werte von float 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.
+0

Ich appreciate Ihre Antwort, und ich denke, dass ich einen anderen Weg finden muss. Aber siehe oben EDIT.Obwohl der NSLog das "falsche" Format angibt, wird es korrekt verwendet. Ich werde sehen, ob ich mit einer der oben genannten Methoden bessere Ergebnisse erziele. –

+1

@ B-Man, der C 'float' Typ kann keine perfekte Rundung versprechen. Wenn Sie dies benötigen, verwenden Sie einen anderen Datentyp. Sie können Roll Your Own und den Wert im NSInteger-Wert von 100. beibehalten, oder Sie können einen anderen Datentyp wie [NSDecimal] (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation) verwenden /Classes/NSDecimalNumber_Class/Reference/Reference.html) aufgelistet. – bshirley

10

Sie tun das in Objective-C genau das gleiche, wie Sie es in C:

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

nicht float verwenden - es sei denn, Sie jemand erklären kann, genau das, was Ihre spezifischen Gründe sind Schwimmer zu verwenden über doppelt. Schwimmer hat eine sehr begrenzte Genauigkeit. Und die Verwendung von Ceil oder Boden ist doof, da es eine vollkommen feine Standardfunktion namens "rund" gibt.

Weder float noch double genau repräsentieren die meisten Dezimalwerte, wie 12,24. Weil es eine viel höhere Präzision hat, wird das Doppelte viel näher an 12.24 kommen. Daher gibt es eine große Chance, dass NSLog eine seltsame Zahl für (float) 12.24, wie 12.23999997394 oder was auch immer anzeigt, während es 12.24 für double anzeigen kann.

+1

Danke für die Antwort. Double ist der richtige Weg. Ich habe schon vor einiger Zeit eine Antwort gewählt, also denke ich, dass ich nur deine Antwort aufsetzen kann. Vielen Dank für Ihre Zeit zu erklären, sehr geschätzt. –

1

Fehler in dieser Zeile

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

korrigieren zu

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