web-dev-qa-db-fra.com

iOS Objective-C Comment obtenir une valeur flottante arrondie à 2 décimales?

J'ai un

float a = 1412.244019;

et j'ai besoin d'un arrondi à la seconde décimale la plus proche, comme 1412.24000000. Je comprends que si je veux présenter un avec seulement deux décimales, j'utilise% .2f, mais ce n'est PAS le cas. J'ai besoin du nouveau un pour des raisons mathématiques comme flotteur.

J'ai essayé quelques méthodes trouvées sur stackoverflow sans chance. Le plus évident que j'ai utilisé, je le mentionne ci-dessous, mais je n'ai toujours pas eu de chance de l'utiliser. Pouvez-vous voir pourquoi la magie ne se produit pas?

PS: Il fait parfois l'effet désiré, PAS toujours, ce qui me fait penser ... hmmm ...

Merci d'avance.

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

MODIFIER:

SEMBLE comme lorsque j'utilise le flotteur a après la chirurgie ci-dessus, il considère que c'est 1412.240000 même si le NSLog dit différemment ... étrange. Mais je reçois ce que je veux, alors bravo pour le temps perdu à ne rien courir :)

MODIFIER J'aimerais vous choisir tous comme bonnes réponses, mais comme je ne peux en choisir qu'une, j'ai choisi la première bonne réponse avec des explications supplémentaires (des deux dernier).

29
B-Man

Avez-vous essayé cela?

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: arrondir le nombre à 2 décimales en C

Complémentaire: Vous n'avez tout simplement pas de contrôle sur la façon dont l'ordinateur stockera la valeur flottante.

Donc, ces valeurs arrondies peuvent ne pas être EXACTEMENT les valeurs décimales "évidentes", mais elles seront très très proches, et c'est la garantie maximale que vous aurez.

58
Lucas Eduardo

Vous faites cela dans Objective-C exactement comme vous le feriez dans C:

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

N'utilisez pas float - sauf si vous pouvez expliquer à quelqu'un exactement quelles sont vos raisons spécifiques d'utiliser float over double. float a une précision très limitée. Et utiliser un plafond ou un sol est idiot, car il existe une fonction standard parfaitement fine nommée "rond".

Ni float ni double ne peuvent exactement représenter la plupart des valeurs décimales, comme 12.24. Parce qu'il a une précision beaucoup plus élevée, le double vous permettra de vous rapprocher de 12,24. Par conséquent, il y a une énorme chance que NSLog affiche un nombre étrange pour (float) 12.24, comme 12.23999997394 ou autre, alors qu'il peut afficher 12.24 pour double.

11
gnasher729

Erreur dans cette ligne

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

le corriger pour

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

La valeur la plus proche de 1412.24 qu'un float peut avoir est 1412.239990234375. Il existe une opération no qui peut produire un float plus proche que cela, car le format des objets float ne représente pas de valeurs plus proches. Demander à représenter 1412,24 dans float revient à demander de représenter 2,5 dans int. Ça ne peut tout simplement pas être fait.

Les options pour y faire face incluent:

  • Vous pouvez utiliser une mise en forme qui affiche "1412.24", sans modifier l'objet float sous-jacent.
  • Vous pouvez utiliser double pour vous rapprocher (beaucoup plus près), mais ce ne sera toujours pas exactement 1412.24.
  • Vous pouvez mettre à l'échelle les valeurs de float en valeurs représentables (par exemple, mesurer dans d'autres unités de sorte que les valeurs souhaitées soient toutes exactement représentables en float).
  • Vous pouvez utiliser un type de données différent, tel que NSDecimal.
5
Eric Postpischil

Vous ne pouvez pas forcer une valeur flottante. Les flottants sont conçus pour être quelque peu approximatifs, car leur ampleur peut être grande, et comme vous n'avez que peu de bits à utiliser, il peut se rapprocher, mais pas exactement, exprimer un nombre décimal.

Une suggestion est de faire toute votre arithmétique en entier, multiplié par 100, puis en divisant lorsque vous voulez afficher votre résultat final. Vous pouvez avoir des nombres trop grands qui interdiraient cela.

2
Owen Hartnett

Vous pouvez multiplier a par 100,0 et peut-être ajouter 0,5 pour l'arrondi, puis prendre la valeur int du résultat. Vous pouvez ensuite utiliser/100 pour obtenir la valeur avant la virgule décimale et% 100 pour obtenir les deux décimales.

2
David Elliman