1 votes

Comment effectuer un calcul précis des devises dans une application iPhone ?

J'ai écrit une application iPhone qui calcule un coût total en ajoutant/soustrayant des unités de coût prédéterminé. Cela fonctionnait bien jusqu'à ce que je me rende compte que les valeurs flottantes que j'utilisais rendaient le total inexact. J'ai donc commencé à chercher à utiliser NSDecimalNumber. Je suis maintenant assez confus et j'ai une erreur 'out of scope'. Les sections pertinentes de mon code (simplifié) sont ci-dessous. Comment puis-je faire en sorte que cela fonctionne comme prévu ?

MyViewController.h

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController {
    IBOutlet UILabel *totalPrice;
    NSDecimalNumber *total;
    NSDecimalNumber *item1Price;
}

@property (retain, nonatomic) NSDecimalNumber *total;
@property (retain, nonatomic) UILabel *totalPrice;

- (IBAction)addItem:(id)sender;
- (void)getDefaults;
- (void)setLabels;
@end

MyViewController.m

#import "MyViewController.h"

@implementation MyViewController

@synthesize total;
@synthesize totalPrice;

- (void)getDefaults {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"prices" ofType:@"plist"];
    NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
    total = [NSDecimalNumber decimalNumberWithString:@"0"];
    item1Price = (NSDecimalNumber *)[dict valueForKey:@"item1"];
}

- (void)setLabels {
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [numberFormatter setCurrencySymbol:@"£"];
    [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    totalPrice.text = [numberFormatter stringFromNumber:total];
}

- (void)viewDidLoad {
    [self getDefaults];
    [self setLabels];
}

- (IBAction)addItem:(id)sender {
    NSDecimalNumber *itemPrice;

    switch ([sender tag]) {
        case 1:
            itemPrice = item1Price;
            break;
    }

    total = [total decimalNumberByAdding:itemPrice];

    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [numberFormatter setCurrencySymbol:@"£"];
    [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];

    totalPrice.text = [numberFormatter stringFromNumber:total];
}

@end

J'espère que je suis sur la bonne voie...

1voto

jessecurry Points 12114

Vous pouvez utiliser des nombres entiers pour faire le calcul, il suffit de multiplier la partie fractionnaire et de diviser pour revenir à la valeur correcte.

Sinon, vous pouvez essayer un double, c'est ce qui est utilisé pour la plupart des types de données du SDK qui nécessitent une précision (par exemple, CLLocationCoordinate, NSTimeInterval).

1voto

imnk Points 2576

Votre erreur hors champ pourrait provenir du fait que 'total' et 'itemPrice1' sont définis comme une variable d'instance et sont utilisés en tant que tels, c'est-à-dire que vous les utilisez dans toute la classe. La méthode getDefaults définit leurs valeurs, qui sont ensuite utilisées dans d'autres méthodes. Cependant, en initialisant ces variables comme :

 total = [NSDecimalNumber decimalNumberWithString:@"0"];
item1Price = (NSDecimalNumber *)[dict valueForKey:@"item1"];

...ils se libèrent automatiquement à la fin de cette méthode (dans cette portée). Vous avez deux options pour initialiser :

total = [[NSDecimalNumber decimalNumberWithString:@"0"] retain];
// OR
total = [[NSNumber alloc] initWithString:@"0"];

Quelle que soit l'option que vous choisissez parmi les deux ci-dessus, vous devrez libérer plus tard (généralement dans la méthode dealloc de la classe).

Je ne sais pas quel était le problème en utilisant NSNumber. Vous avez mentionné que les flottants n'étaient pas assez précis, dans ce cas, j'utiliserais simplement un double à la place. Vous pourriez faire ceci :

double totalSetter = 0.0;
NSNumber *total = [[NSNumber alloc] initWithDouble:totalCaster];

et ensuite les récupérer en utilisant :

double totalGetter = [total doubleValue];

Vous devriez maintenant être en mesure d'utiliser le NSNumberFormatter avec les NSNumbers que vous avez créés.

0voto

Dave Hunt Points 6327

Il y avait deux problèmes ici. L'un était l'erreur de portée, que j'ai résolu en utilisant retain comme suggéré par imnk. Je l'avais déjà essayé mais mon decimalNumberByAdding donnait des résultats inexacts.

Il s'avère que malgré la mise en place itemPrice1 en tant que NSDecimalNumber la ligne :

item1Price = (NSDecimalNumber *)[dict valueForKey:@"item1"];

était de le changer en un NSCFNumber . Pour résoudre ce problème, j'ai transformé cette variable en une NSString et a créé un NSDecimalNumber de la chaîne pour l'utiliser dans ma méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X