简介
ios开发中有时我们需要把NSNumber
转化为NSString
类型,会出现转化不准确的现象.
比如后台定义了一个82.4,我们接收到数据,并转化为NSString
类型,结果会显示出82.39999999999999999.试过几次后发现是double
转化为NSNumber
的时候除了问题.
double
表示的字面值和其存储的值一般是不一样的,转化为NSNumber
之后,有很大一些数字,在NSNumber
的stringValue
上会出错。
解决方法:
可以是取NSString
的doubleValue
,然后再.2f保留两位小数进行构造字符串。千万不能取floatValue
,floatValue
在大于15万的浮点数字就会出现不精确了 。而doubleValue
在数十亿的范围内都是字面上精确的。
如果涉及到计算的问题,需要把字符串转化为NSDecimalNumber
对象,再转成字符串。
下面附上一套格式化数字类型字符串的方法:
typedef NS_ENUM(NSUInteger, EHNumberFormatterStyle) {
EHNumberFormatterIntegerStyle = 0,//123,456,7
EHNumberFormatterDecimalStyle, //12,345.67
EHNumberFormatterFractionDecimalStyle, // 小数为0舍去 12,345.0 => 12,345 12,345.1=>12,345.1
EHNumberFormatterCurrencyPrefixIntegerStyle, //¥123,456,7
EHNumberFormatterCurrencySuffixIntegerStyle, //123,456,7元
EHNumberFormatterCurrencySuffixDecimalStyle, //12,345.67元
EHNumberFormatterCurrencyTenThousandStyle, //123万
EHNumberFormatterCurrencyTenThousandDecimalStyle, //123.4万
EHNumberFormatterAreaStyle, //123m²
EHNumberFormatterAreaPriceStyle, //1,234元/m²
EHNumberFormatterRentPriceStyle, //1,234元/月
EHNumberFormatterPercentStyle, // +1.23% , -1.23%
EHNumberFormatterUnsignedPercentStyle // 1.23% -1.23%
};
/*
style 格式化类型
decimalPlace 精确度
symbol 为空时返回字符串
prefix 正负符号的追加格式
suffix 单位符号的追加格式
*/
+(NSString *)stringWithNumberStyle:(EHNumberFormatterStyle)style data:(id)data decimalPlace:(NSInteger)decimalPlace nullOrZeroSymbol:(NSString*)symbol prefix:(NSString*)prefix suffix:(NSString*)suffix{
NSNumberFormatter *formatter;
NSNumber *num;
if(![data isKindOfClass:[NSString class]] && ![data isKindOfClass:[NSNumber class]]){
num = @(0);
}
if([data isKindOfClass:[NSString class]]){
formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
num = [formatter numberFromString:data];
if(!num) num = @(0);
}else{
num = data;
}
NSString *result;
if(num && num.boolValue){
if(style == EHNumberFormatterIntegerStyle)
{
formatter = [self formatterFromNumberStyle:EHNumberFormatterIntegerStyle decimalPlace:decimalPlace];
result = [formatter stringFromNumber:num];
}
else if(style == EHNumberFormatterDecimalStyle)
{
formatter = [self formatterFromNumberStyle:EHNumberFormatterDecimalStyle decimalPlace:decimalPlace];
result = [formatter stringFromNumber:num];
}
else if(style == EHNumberFormatterFractionDecimalStyle)
{
formatter = [self formatterFromNumberStyle:EHNumberFormatterFractionDecimalStyle decimalPlace:decimalPlace];
result = [formatter stringFromNumber:num];
}
else if(style == EHNumberFormatterCurrencyPrefixIntegerStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterIntegerStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"¥" suffix:@""];
}
else if(style == EHNumberFormatterCurrencyPrefixDecimalStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterDecimalStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"¥" suffix:@""];
}
else if(style == EHNumberFormatterCurrencySuffixIntegerStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterIntegerStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"元"];
}
else if(style == EHNumberFormatterCurrencySuffixDecimalStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterDecimalStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"元"];
}
else if(style == EHNumberFormatterCurrencyTenThousandStyle)
{
num = @(num.doubleValue/10000);
result = [self stringWithNumberStyle:EHNumberFormatterIntegerStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"万"];
}
else if(style == EHNumberFormatterCurrencyTenThousandDecimalStyle)
{
num = @(num.doubleValue/10000);
result = [self stringWithNumberStyle:EHNumberFormatterFractionDecimalStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"万"];
}
else if(style == EHNumberFormatterAreaStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterFractionDecimalStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"m²"];
}
else if(style == EHNumberFormatterAreaPriceStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterIntegerStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"元/m²"];
}
else if(style == EHNumberFormatterRentPriceStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterIntegerStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"元/月"];
}
else if(style == EHNumberFormatterPercentStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterDecimalStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:[num doubleValue]>=0?@"+":@"" suffix:@"%"];
}
else if(style == EHNumberFormatterUnsignedPercentStyle)
{
result = [self stringWithNumberStyle:EHNumberFormatterDecimalStyle data:data decimalPlace:decimalPlace nullOrZeroSymbol:symbol prefix:@"" suffix:@"%"];
}
}
if([result eh_hasData]){
result = [NSString stringWithFormat:@"%@%@%@",prefix,result,suffix];
}else{
result = symbol ?: @"";
}
return result;
}
+(NSNumberFormatter*)formatterFromNumberStyle:(EHNumberFormatterStyle)style decimalPlace:(NSInteger)decimalPlace{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
if(style == EHNumberFormatterIntegerStyle)
{
formatter = [[NSNumberFormatter alloc] init];
formatter.groupingSize = 3;
formatter.groupingSeparator = @",";
formatter.usesGroupingSeparator = NO;
}
else if(style == EHNumberFormatterDecimalStyle)
{
formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.roundingMode = NSNumberFormatterRoundCeiling;
formatter.maximumFractionDigits = decimalPlace;
formatter.minimumFractionDigits = decimalPlace;
}
else if(style == EHNumberFormatterFractionDecimalStyle)
{
formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.roundingMode = NSNumberFormatterRoundCeiling;
formatter.maximumFractionDigits = decimalPlace;
}
return formatter;
}