iOS開(kāi)發(fā)中,接受后臺(tái)的響應(yīng),把json然后轉(zhuǎn)化為模型對(duì)象,最終轉(zhuǎn)化為NSString對(duì)象。
后臺(tái)返回的一個(gè)數(shù)字(這里一般是商品價(jià)格,因?yàn)橹挥懈X相關(guān)的東西才會(huì)特別特別的謹(jǐn)慎,畢畢竟出了事是要負(fù)責(zé)的,還好前端只是展示價(jià)格,真正出錯(cuò)是后臺(tái)),可以定義為NSnumber類型,也可以定義為NSString問(wèn)題。如果后臺(tái)返回的是字符串類型。在iOS json序列化的時(shí)候,會(huì)把字符串類型轉(zhuǎn)化為NSString對(duì)象,這個(gè)一點(diǎn)問(wèn)題沒(méi)有。但是如果后臺(tái)返回的是NSnumber類型。json序列化會(huì)將NSnumber類型轉(zhuǎn)化為NSNumber對(duì)象。使用的時(shí)候,想當(dāng)然的會(huì)將NSNumber轉(zhuǎn)化為NSString對(duì)象(NSString *pricer = [NSString stringWithFormat:@"%@",number] )。這樣做很自然啊,沒(méi)有問(wèn)題,也用一兩個(gè)數(shù)字測(cè)試了,轉(zhuǎn)化是精確的。But問(wèn)題來(lái)了,假如后臺(tái)定義的是double類型數(shù)據(jù)89.6,你轉(zhuǎn)化后的字符串會(huì)發(fā)現(xiàn)就是89.59999999999999,直接用NSString接收后臺(tái)的double就會(huì)有問(wèn)題,double字面數(shù)值和和其存儲(chǔ)的值不一樣。
類型? ? ? ? ? ? ? ? ? ? ? ? 比特?cái)?shù) ? ? ? ?有效數(shù)字? ? ? ? ? ? ? ? 數(shù)值范圍
float 類型 ? ? ? ? ? ? ? ? 32 ? ? ? ? ? ? ? ?6-7? ? ? ? ? ? ? ? -3.4*10(-38)~3.4*10(38)
double類型 ? ? ? ? ? ? ? 64 ? ? ? ? ? ? ?15-16? ? ? ? ? ? -1.7*10(-308)~1.7*10(308)
long double類型 ? ? ?128 ? ? ? ? ? ? 18-19? ? ? ? ? -1.2*10(-4932)~1.2*10(4932)
NSDecimalNumber是NSNumber的不可變子類。蘋果針對(duì)浮點(diǎn)型計(jì)算時(shí)存在精度計(jì)算誤差的問(wèn)題而提供的一個(gè)計(jì)算類,它是基于10進(jìn)制的定點(diǎn)計(jì)算保證了精度不會(huì)缺失。同時(shí)也可以定制精度的取正類型:向上取正、向下去正、四舍五入等。相對(duì)與浮點(diǎn)類型的計(jì)算,NSDecimalNumber提供了更加精準(zhǔn)的計(jì)算。下面是NSDecimalNumber的一個(gè)類別,主要是加減乘除:
.h文件
typedef NS_ENUM(NSInteger, calculationType) {
Add,
Subtract,
Multiply,
Divide
};
@interface NSDecimalNumber (Addtion)
+(NSDecimalNumber *)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 type:(calculationType)type anotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2 andDecimalNumberHandler:(NSDecimalNumberHandler *)handler;
+(NSComparisonResult)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2;
+(NSString *)stringWithDecimalNumber:(NSDecimalNumber *)str1 scale:(NSInteger)scale;
extern NSComparisonResult StrNumCompare(id str1,id str2);
extern NSDecimalNumber *handlerDecimalNumber(id strOrNum,NSRoundingMode mode,int scale);
extern NSComparisonResult SNCompare(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNAdd(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNSub(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNMul(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNDiv(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNMin(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNMax(id strOrNum1,id strOrNum2);
extern NSDecimalNumber *SNAdd_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
extern NSDecimalNumber *SNSub_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
extern NSDecimalNumber *SNMul_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
extern NSDecimalNumber *SNDiv_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
extern NSDecimalNumber *SNMin_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
extern NSDecimalNumber *SNMax_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
@end
.m文件
+(NSDecimalNumber *)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 type:(calculationType)type anotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2 andDecimalNumberHandler:(NSDecimalNumberHandler *)handler{
if (!stringOrNumber2 || !stringOrNumber1) {
NSLog(@"輸入正確類型");
return nil;
}
NSDecimalNumber *one;
NSDecimalNumber *another;
NSDecimalNumber *returnNum;
if ([stringOrNumber1 isKindOfClass:[NSString class]]) {
one = [NSDecimalNumber decimalNumberWithString:stringOrNumber1];
}else if([stringOrNumber1 isKindOfClass:[NSDecimalNumber class]]){
one = stringOrNumber1;
}else if ([stringOrNumber1 isKindOfClass:[NSNumber class]]){
one = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber1 decimalValue]];
}else{
NSLog(@"輸入正確的類型");
return nil;
}
if ([stringOrNumber2 isKindOfClass:[NSString class]]) {
another = [NSDecimalNumber decimalNumberWithString:stringOrNumber2];
}else if([stringOrNumber2 isKindOfClass:[NSDecimalNumber class]]){
another = stringOrNumber2;
}else if ([stringOrNumber2 isKindOfClass:[NSNumber class]]){
another = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber2 decimalValue]];
}else{
NSLog(@"輸入正確的類型");
return nil;
}
if (type == Add) {
returnNum = [one decimalNumberByAdding:another];
}else if (type == Subtract){
returnNum? = [one decimalNumberBySubtracting:another];
}else if (type == Multiply){
returnNum = [one decimalNumberByMultiplyingBy:another];
}else if (type == Divide){
if ([NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:another compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:@(0)] == 0) {
returnNum = nil;
}else
returnNum = [one decimalNumberByDividingBy:another];
}else{
returnNum = nil;
}
if (returnNum) {
if (handler) {
return [returnNum decimalNumberByRoundingAccordingToBehavior:handler];
}else{
return returnNum;
}
}else{
NSLog(@"輸入正確的類型");
return nil;
}
}
+(NSComparisonResult)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2{
if (!stringOrNumber2 || !stringOrNumber1) {
NSLog(@"輸入正確類型");
return -404;
}
NSDecimalNumber *one;
NSDecimalNumber *another;
if ([stringOrNumber1 isKindOfClass:[NSString class]]) {
one = [NSDecimalNumber decimalNumberWithString:stringOrNumber1];
}else if([stringOrNumber1 isKindOfClass:[NSDecimalNumber class]]){
one = stringOrNumber1;
}else if ([stringOrNumber1 isKindOfClass:[NSNumber class]]){
one = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber1 decimalValue]];
}else{
NSLog(@"輸入正確的類型");
return -404;
}
if ([stringOrNumber2 isKindOfClass:[NSString class]]) {
another = [NSDecimalNumber decimalNumberWithString:stringOrNumber2];
}else if([stringOrNumber2 isKindOfClass:[NSDecimalNumber class]]){
another = stringOrNumber2;
}else if ([stringOrNumber2 isKindOfClass:[NSNumber class]]){
another = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber2 decimalValue]];
}else{
NSLog(@"輸入正確的類型");
return -404;
}
return [one compare:another];
}
+(NSString *)stringWithDecimalNumber:(NSDecimalNumber *)str1 scale:(NSInteger)scale{? ?
?if (!str1) {? ? ? ??
return @"";? ?
?}? ??
NSString *str = [NSString stringWithFormat:@"%@",str1];??
? if (str && str.length) {? ? ??
? if ([str rangeOfString:@"."].length == 1) {//有小數(shù)點(diǎn)? ?
?? ? ? ? NSArray *arr = [str componentsSeparatedByString:@"."];? ? ? ? ??
? if (scale > 0) {? ? ? ? ? ? ??
? NSInteger count = [arr[1] length];? ? ? ? ? ?
?? ? for (NSInteger i = count; i<scale;i++) {
? ? str = [str stringByAppendingString:@"0"];
? ?}
? ? return str;?
? ? ? else{
? ? ? return arr[0];
? ? }
else{ //沒(méi)有小數(shù)點(diǎn)
if ([str rangeOfString:@"."].length) {
return @"";
}
if (scale > 0) {
str = [str stringByAppendingString:@"."];
for (int i = 0; i<scale;i++){
str = [str stringByAppendingString:@"0"];
}
return str;
}
else{
? return str;
}
}
}else{
return @"";
}
NSComparisonResult StrNumCompare(id str1,id str2){
return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:str1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:str2];
}
NSDecimalNumber *handlerDecimalNumber(id strOrNum,NSRoundingMode mode,int scale){
if (!strOrNum) {
NSLog(@"輸入正確類型");
return nil;
}else{
NSDecimalNumber *one;
if ([strOrNum isKindOfClass:[NSString class]]) {
one = [NSDecimalNumber decimalNumberWithString:strOrNum];
}else if([strOrNum isKindOfClass:[NSDecimalNumber class]]){
one = strOrNum;
}else if ([strOrNum isKindOfClass:[NSNumber class]]){
one = [NSDecimalNumber decimalNumberWithDecimal:[strOrNum decimalValue]];
}else{
NSLog(@"輸入正確的類型");
return nil;
}
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:mode scale:scale raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
return? [one decimalNumberByRoundingAccordingToBehavior:handler];
}
}
NSDecimalNumber *SNAdd(id strOrNum1,id strOrNum2){
return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Add anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
}
NSDecimalNumber *SNSub(id strOrNum1,id strOrNum2){
return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Subtract anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
}
NSDecimalNumber *SNMul(id strOrNum1,id strOrNum2){
return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Multiply anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
}
NSDecimalNumber *SNDiv(id strOrNum1,id strOrNum2){
return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Divide anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
}
NSComparisonResult SNCompare(id strOrNum1,id strOrNum2){
return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2];
}
NSDecimalNumber *SNMin(id strOrNum1,id strOrNum2){
return SNCompare(strOrNum1, strOrNum2) > 0 ? strOrNum2 : strOrNum1;
}
NSDecimalNumber *SNMax(id strOrNum1,id strOrNum2){
return SNCompare(strOrNum1, strOrNum2) > 0 ? strOrNum1 : strOrNum2;
}
NSDecimalNumber *SNAdd_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
return handlerDecimalNumber(SNAdd(strOrNum1, strOrNum2), mode, scale);
}
NSDecimalNumber *SNSub_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
return handlerDecimalNumber(SNSub(strOrNum1, strOrNum2), mode, scale);
}
NSDecimalNumber *SNMul_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
return handlerDecimalNumber(SNMul(strOrNum1, strOrNum2), mode, scale);
}
NSDecimalNumber *SNDiv_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
return handlerDecimalNumber(SNDiv(strOrNum1, strOrNum2), mode, scale);
}
NSDecimalNumber *SNMin_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
return handlerDecimalNumber(SNMin(strOrNum1, strOrNum2), mode, scale);
}
NSDecimalNumber *SNMax_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
return handlerDecimalNumber(SNMax(strOrNum1, strOrNum2), mode, scale);
}
使用:在使用到處理精度的類導(dǎo)入頭文件#import "NSDecimalNumber+Addtion.h"
NSDecimalNumber *num = [[NSDecimalNumber alloc] initWithString:@"0.00"];
NSDecimalNumber *num1 = [[NSDecimalNumber alloc] initWithString:@"0.00"];
NSDecimalNumber *num2 = [[NSDecimalNumber alloc] initWithString:@"0.00"];
NSString *priceStr = @"89.6";
//加法運(yùn)算
num = SNAdd(num1,num2);
//減法運(yùn)算
num = SNSub(num1,num2);
//乘法運(yùn)算
num = SNMul(num1,num2);
//除法運(yùn)算
num = SNDiv(num1,num2);
//加法乘法混合運(yùn)算
num = SNAdd(SNMul(@(數(shù)量),價(jià)格), num2);
//最終結(jié)果
NSString *result = [NSString stringWithFormat:@"%@",num];