iOS開發:Objective-C精確的貨幣計算


在iOS開發中,和貨幣價格計算相關的,需要注意計算精度的問題。即使只是兩位小數,也會出現誤差。使用float類型運算,是完全不夠的。經過一番測試,最后選擇使用系統提供的API的NSDecimalNumber來進行更好的解決。

作為一個對外的庫,鑒於版本延續,我們保留對外的flaot的類型,不改變接口,選擇進行內部適配。

以下是一些基本的測試,

原始數據

float a = 0.01;

int b = 99999999;

double c = 0.0;

1:使用浮點運算,

c = a*b;

NSLog(@"%f",c);

NSLog(@"%.2f",c);

使用double類型存儲沒有觸及問題的實質,完全不能解決。

2011-12-30 11:04:00.121 Untitled[2912:207] 1000000.000000

2011-12-30 11:04:00.123 Untitled[2912:207] 1000000.00

 

2:使用類型轉換,提高精度

c = a*(double)b;

NSLog(@"%f",c);

NSLog(@"%.2f",c);

Double運算的精度是提高了,可是浮點數的數值早已經出現了精度的不准確,即使存儲空間足夠,同樣還是不准確的數值。

2011-12-30 11:04:00.123 Untitled[2912:207] 999999.967648

2011-12-30 11:04:00.124 Untitled[2912:207] 999999.97

 

3:通過和NSString的轉換,將計算的原始數據轉換為純粹的double類型的數據,這樣的計算精度就可以達到要求了。

NSString *objA = [NSString stringWithFormat:@"%.2f", a];

NSString *objB = [NSString stringWithFormat:@"%.2f", (double)b];

c = [objA doubleValue] * [objB doubleValue];

NSLog(@"%.2f",c);

計算的結果還是比較准確的,不過需要做格式化輸入和格式化輸出的處理。同時使用NSString來轉換,這樣的寫法看起來比較奇怪。

2011-12-30 11:04:00.190 Untitled[2912:207] 999999.99

 

4:個人還是比較喜歡使用系統提供的類型來進行計算。通過NSDecimalNumber提供的計算方式,可以很好的計算出准確的精度的數據,同時不需要使用格式化輸出等。

其計算的精度是比較高,這是官方建議的貨幣計算的API,對乘除等計算都有單獨的API接口來提供。

NSString *decimalNumberMutiplyWithString(NSString *multiplierValue,NSString *multiplicandValue)

{

     NSDecimalNumber *multiplierNumber = [NSDecimalNumber decimalNumberWithString:multiplierValue];

     NSDecimalNumber *multiplicandNumber = [NSDecimalNumber decimalNumberWithString:multiplicandValue];

     NSDecimalNumber *product = [multiplicandNumber decimalNumberByMultiplyingBy:multiplierNumber];

     return [product stringValue];

}

 

NSLog(@"%@",decimalNumberMutiplyWithString([NSString stringWithFormat:@"%f",a], [NSString stringWithFormat:@"%d",b]));

 

2011-12-30 11:04:00.251 Untitled[2912:207] 999999.99

 

只是測試,所以接口名大致寫寫,名字取得比較不那么講究,希望可以表達清楚。

 

總的來說,對於貨幣計算,應該需要注意精度的問題。同時在運算的時候,應該優先選用框架提供的API,否則,就應該使用足夠精度的類型運算,同時對自己寫的接口進行足夠的說明,要求開發者按照規范來使用。

在自己不能保證足夠准確的情況下,用適當的說明的要求來規避責任還是可以接受的。至少被人抱怨兩句總比出錯強。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM