我编写了一款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
我希望我走在正确的道路上......
答案 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
以在我的方法中使用它。