iOS開發中有時需要我們精度的嚴格處理,比如關於用戶資金的數目處理,比較好的建議是服務端直接返回金額數目為字符串類型,這樣客戶端就不用擔心精度顯示了,如果我們需要對服務端返回過來的數據進行操作,比如:服務端兩個數字float a = 0.01, int b = 99999999,兩數相乘的結果是999999.99,就需要考慮精度的問題了。再比如對 flat a = 123456789.12,int b = 10000,兩數相除
在iOS開發中,和貨幣價格計算相關的,需要註意計算精度的問題。即使只是兩位小數,也會出現誤差。使用float類型運算,是完全不夠的。經過壹番測試,最後選擇使用系統提供的API的NSDecimalNumber來進行更好的解決。
作為壹個對外的庫,鑒於版本延續,我們保留對外的flaot的類型,不改變接口,選擇進行內部適配。
以下是壹些基本的測試,
原始數據
floata =0.01;
intb =99999999;
doublec =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 = [NSStringstringWithFormat:@"%.2f", a];
NSString*objB = [NSStringstringWithFormat:@"%.2f", (double)b];
c = [objAdoubleValue] * [objBdoubleValue];
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 = [NSDecimalNumberdecimalNumberWithString:multiplierValue];
NSDecimalNumber*multiplicandNumber = [NSDecimalNumberdecimalNumberWithString:multiplicandValue];
NSDecimalNumber*product = [multiplicandNumberdecimalNumberByMultiplyingBy:multiplierNumber];
return[productstringValue];
}
NSLog(@"%@",decimalNumberMutiplyWithString([NSStringstringWithFormat:@"%f",a], [NSStringstringWithFormat:@"%d",b]));
2011-12-30 11:0 4:00.251 Untitled[2912:207] 999999.99
只是測試,所以接口名大致寫寫,名字取得比較不那麽講究,希望可以表達清楚。
總的來說,對於貨幣計算,應該需要註意精度的問題。同時在運算的時候,應該優先選用框架提供的API,否則,就應該使用足夠精度的類型運算,同時對自己寫的接口進行足夠的說明,要求開發者按照規範來使用。
在自己不能保證足夠準確的情況下,用適當的說明的要求來規避責任還是可以接受的。至少被人抱怨兩句總比出錯強。