2009-12-04 62 views
1

我写的iPhone应用程序,其计算由加/减预定成本的单元的总成本执行精确的计算货币。这是工作的罚款,直到我意识到,我用的是浮点值造成的总不准确,所以我开始考虑使用NSDecimalNumber。我现在很困惑,并有一个'超出范围'的错误。下面是我的(简化)代码的相关部分。我如何才能让它按预期工作?如何在iPhone应用程序

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

很多时候,金钱计算是用整数,乘以100(或1K或10K),做数学,然后将它们分开(参见谷歌的货币计算算法)。花车太不准确(.1 + .2并不是必需的.3)。 – KevinDTimm 2009-12-04 16:32:14

+0

“范围外”错误和var名称是什么? – zaph 2009-12-04 16:39:27

+0

当我添加一个项目时,总变量超出了范围,但是我的问题更多的是如何“正确地”执行此操作,而不是专门修复当前的错误,除非这两个问题的答案当然会发生要一样! – 2009-12-04 16:44:09

回答

0

有这里有两个问题。其中一个是范围错误,我使用imnk建议的解决方案使用retain。我已经尝试了这一点,但我的decimalNumberByAdding提供了不准确的结果。

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

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

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

1

你可以使用整数做计算,只是乘出的小数部分,分化,回到正确的值。

否则,你可能想尝试双,这就是实际用于最需要的精度SDK的数据类型(即:CLLocationCoordinate,NSTimeInterval)。

+0

谢谢,我绝对考虑这是一个选项!幸运的是,我设法解决了“NSDecimalNumber”解决方案,这一直是我的首选。 – 2009-12-07 08:56:49

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。你提到float没有足够精确,在这种情况下,我只会使用double。你可以这样做:

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

,然后检索使用:

double totalGetter = [total doubleValue]; 

现在,你应该能够使用NSNumberFormatter与你所做的NSNumbers。

+0

干杯,这是我解决问题的一部分。很有帮助! – 2009-12-07 08:55:20