财务的NSDecimalNumber

时间:2015-06-04 14:41:16

标签: ios objective-c nsnumber nsdecimalnumber

我正在构建一个处理金钱的应用程序,直到现在我一直在使用浮点运算,但我已经了解到使用NSDecimalNumber会更好。

我想确保我已正确理解它,所以这里是:

想象一下一些工人,每小时收入20.57美元。该信息由用户提供。我之前做过这样的事情:

@property (nonatomic) float hourlyRate;

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *hourlyRate = [numberFormatter numberFromString:self.rateTextField.text];
settingsObject.hourlyRate = [hourlyRate floatValue];

但我现在改为:

@property (nonatomic) NSDecimalNumber *hourlyRate;

settingsObject.hourlyRate = (NSDecimalNumber *)[NSDecimalNumber decimalNumberWithString:self.rateTextField.text locale:[NSLocale currentLocale]];

这是从字符串中读取NSDecimalNumbers的正确方法吗?

说这个人在10:01进入工作场所。我保存了这样的信息:

[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"start"];

完成此人后,将从NSUserDefaults中读取开始时间,如下所示:

NSDate *start = [[NSUserDefaults standardUserDefaults] objectForKey:@"start"];

持续时间的计算如下:

NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:start] / 3600;

NSDecimalNumber *earned = [settingsObject.hourlyRate decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithFloat:interval]];

这是正确而有效的方法,同时保持精确度吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

  

这是从字符串中读取NSDecimalNumbers的正确方法吗?

是。但是,您不需要转换结果。所以它应该是这样的:

settingsObject.hourlyRate = [NSDecimalNumber decimalNumberWithString:self.rateTextField.text locale:[NSLocale currentLocale]];

除非您使用的是非当前区域设置,否则NSLocale部分不是必需的:

settingsObject.hourlyRate = [NSDecimalNumber decimalNumberWithString:self.rateTextField.text];

我不认为此函数喜欢nil值,因此您需要确保rateTextField首先具有非零值:

if ([self.rateTextField hasText]) {
    settingsObject.hourlyRate = [NSDecimalNumber decimalNumberWithString:self.rateTextField.text];
}
else {
    settingsObject.hourlyRate = [NSDecimalNumber zero];
}
  

这是正确而有效的方法,同时保持精确度吗?

是的,您将间隔转换为NSDecimal数字然后乘法对我来说很好。

答案 1 :(得分:0)

首先,您需要回答这个问题:

您希望成为多么准确 - 或者您需要做到?

您的应用会生成发票,还是作为发票的基础?如果是,您可能必须远离浮点数。您可能还需要考虑如何在计算中实际使用持续时间。可能存在某些业务领域或专业的法规,这些法规定义了如何衡量/开具发票时间。

不太准确:

如果你不需要非常准确,我会继续使用浮动数字直到遇到障碍物。

<强>准确

<强> 1。钱:

将货币整数存储为美分。

<强> 2。时间:

确定时间段并将它们存储为整数(可能是几分钟)。

第3。计算:

使用整数计算。永远不要使用花车。

<强>详细信息:

如果您有25.07之类的输入(我使用了与20.57不同的数字来解释分数渲染),请将其存储为2507。以美分计算。用于显示转换为$$/hrs。例如:

int amount = 2507;
int amountDollars = amount / 100;
int amountCents = amount % 100;

NSString *output = [NSString stringWithFormat:@"%d.%02d $/hrs", amountDollars, amountCents];
NSLog(@"output = %@", output);
// prints:
// output = 25.07 $/hrs

对于时间选择合适的基本单位(分钟/秒/五分钟/十分钟/半小时?)并将其存储为整数。

让我们假设您以10分钟为单位开具发票。然后你可能会在接下来的10分钟开始计费。因此,如果记录中有11分钟,则必须计算20分钟。几分钟内存在类似的问题 - 假设这些值:

Actual Time | "Integer Time"
10:09:59    |  10:09
10:10:01    |  10:10
Difference:
00:00:02    |  00:01

如果你只是使用浮动点的实际时间,第一个差异几乎没有 - 第二个相当于一分钟。如果您的时间在报告中显示为10:0910:10,那么人们会想知道,为什么在第一种情况下数量几乎为零。

如果您需要非常准确,那么进行财务和时间计算很难。所以归结为:第一,找出你需要的准确度。 (注意&#34;准确&#34;在进入法规,法律等领域时可能具有奇怪的含义和含义。)