2015-06-04 30 views
0

我正在構建一個應付金錢的應用程序,到目前爲止我一直在使用浮點運算,但是我已經瞭解到最好使用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]]; 

這是正確和最有效的方式,同時保持精度?

謝謝!

+0

不要使用float,請使用double。浮點數有6位小數精度,雙精度浮點數有15位。float在年薪中給出了可測量的錯誤。 – gnasher729

+0

@ gnasher729我明白了。這個解決方案與Rainer Schwarze的答案有什麼不同?你對此有何看法? – Erik

回答

0

這是閱讀從字符串NSDecimalNumbers正確的方法是什麼?

是的。但是,您不需要投射結果。因此,它應該只是看起來像這樣:

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

而且NSLocale部分是沒有必要的,除非你使用的是非當前區域:

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

我不認爲這個功能喜歡零值,所以你會希望確保rateTextField具有非零值第一:

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

是這樣的科爾最有效的方式,同時保持精確度?

是的,你的間隔轉化爲NSDecimal號碼,然後乘對我來說很好。

+0

這似乎是處理資金計算的最佳方式。以工作時間跟蹤器爲例,是否真的有必要使用NSDecimalNumber或將雙倍提供?請看Rainer Schwarze的回答。 – Erik

+0

當精度不是那麼重要時,Double可以正常工作。但我隨時隨地用錢工作。使用浮動值並不困難,我認爲代碼比試圖記住需要用整數乘以或除以100的任何地方都更清楚。 –

+0

是的。所以你會建議使用雙工作追蹤應用程序?在NSDecimalNumbers上做算術是令人難以置信的絕望imo,你必須像numberOne = [numberOne decimalNumberByAdding:numberTwo];而不是簡單地numberOne + = numberTwo;這確實使代碼很難維護,閱讀和使用。 – Erik

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 

用於時間選擇一個合適的基站單元(分/秒/5分鐘/ 10分/半小時)並存儲爲一個整數。

讓我們假設您以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,人們會想,爲什麼在第一種情況下,金額幾乎沒有。

如果您需要非常準確,那麼做財務和時間計算就很困難。所以可以歸結爲:首先找出你需要的準確度。 (請注意,在進入法規,法律等領域時,「準確」可能具有奇怪的含義和含義)

+0

非常詳細的答案!謝謝!存儲爲美分,或100倍的用戶提供的每小時費率是一個好主意,我會實現這一點並擺脫浮動。我寫了一個自定義對象來存儲時間值,它也實現了自動省略秒的自定義getter和setter方法。所以我現在正在處理整個分鐘。我只是在需要的時候存儲時間並在運行時計算貨幣。我存儲的唯一財務價值是小時費率。用戶可以選擇將這些信息用於發票,但它基本上是爲了跟蹤工作。 – Erik

+0

我們可以移動聊天嗎? – Erik

+0

@Erik Sure - 你可以照顧開始聊天嗎? –