如何在iPhone应用程序中执行准确的货币计算

时间:2009-12-04 16:19:12

标签: iphone objective-c currency

我编写了一款iPhone应用程序,通过增加/减去预定成本的单位来计算总成本。这工作正常,直到我意识到我使用的浮点值导致总数不准确,所以我开始研究使用NSDecimalNumber。我现在很困惑,并且有一个“超出范围”的错误。我(简化)代码的相关部分如下。我怎样才能让它按预期工作?

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

我希望我走在正确的道路上......

3 个答案:

答案 0 :(得分:1)

您可以使用整数进行计算,只需将小数部分相乘并除以得到正确的值。

否则你可能想尝试一个double,这是大多数需要精度的SDK数据类型实际使用的(即:CLLocationCoordinate,NSTimeInterval)。

答案 1 :(得分:1)


你的超出范围错误可能来自于'total'和'itemPrice1'被定义为实例变量并且被用作这样的事实,即你在整个类中使用它们。 getDefaults方法设置它们的值,然后在其他方法中使用它们。但是,通过将这些变量初始化为:

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

......他们在该方法结束时自动释放(在该范围内)。您有两种初始化选项:

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

无论您从上述两个选项中选择哪个选项,都需要稍后发布(通常在该类的dealloc方法中)。

不确定使用NSNumber的问题是什么。你提到浮动不够准确,在这种情况下我只会用一个双。你可以这样做:

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

然后使用:

进行检索
double totalGetter = [total doubleValue];

现在你应该能够将NSNumberFormatter与你所使用的NSNumber一起使用。

答案 2 :(得分:0)

这里有两个问题。一个是范围错误,我使用了如imnk所建议的retain来解决。我已经试过了,但我的decimalNumberByAdding给出了不准确的结果。

事实证明,尽管将itemPrice1设置为NSDecimalNumber行:

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

正在将其更改为NSCFNumber。为了解决这个问题,我将此变量更改为NSString并从字符串中创建了NSDecimalNumber以在我的方法中使用它。