格式化浮动以进行显示时,限制小数位数和总位数

时间:2012-04-26 16:05:04

标签: objective-c cocoa-touch nsnumberformatter decimal-point

我需要最有效地在有限宽度的区域中打印浮点值。我正在使用NSNumberFormatter,我将小数点后面的两个数字设置为默认值,这样当我有一个像234.25这样的数字时,它会按原样打印:234.25。但是当我1234.25时,我希望将其打印为:1234.311234.25应打印11234

在点之后我需要最多两位数,如果我在点之后有数字,则最多需要五位数,但如果整数部分有更多数字,它也应该打印超过五位数。

我认为无法限制NSNumberFormatter中的总位数。这是否意味着我应该用这种方式编写自己的函数来格式化数字?如果是这样,那么获取数字的整数和小数部分中的数字位数的正确方法是什么?我还希望使用CGFLoat而不是NSNumber来避免额外的类型转换。

4 个答案:

答案 0 :(得分:13)

您正在寻找“最大有效数字”和“最大分数”的组合,以及特定的舍入行为。 NSNumberFormatter等于任务:

float twofortythreetwentyfive = 234.25;
float onetwothreefourtwentyfive = 1234.25;
float eleventwothreefourtwentyfive = 11234.25;

NSNumberFormatter * formatter =  [[NSNumberFormatter alloc] init];
[formatter setUsesSignificantDigits:YES];
[formatter setMaximumSignificantDigits:5];
[formatter setMaximumFractionDigits:2];
[formatter setRoundingMode:NSNumberFormatterRoundCeiling];

NSLog(@"%@", [formatter stringFromNumber:[NSNumber numberWithFloat:twofortythreetwentyfive]]);
NSLog(@"%@", [formatter stringFromNumber:[NSNumber numberWithFloat:onetwothreefourtwentyfive]]);
NSLog(@"%@", [formatter stringFromNumber:[NSNumber numberWithFloat:eleventwothreefourtwentyfive]]);

结果:

  

2012-04-26 16:32:04.481 SignificantDigits [11565:707] 234.25
  2012-04-26 16:32:04.482显着数字[11565:707] 1234.3
  2012-04-26 16:32:04.483 SignificantDigits [11565:707] 11235

答案 1 :(得分:1)

代码:

#define INTPARTSTR(X) [NSString stringWithFormat:@"%d",(int)X]
#define DECPARTSTR(X) [NSString stringWithFormat:@"%d",(int)(((float)X-(int)X)*100)]

- (NSString*)formatFloat:(float)f
{
    NSString* result;

    result = [NSString stringWithFormat:@"%.2f",f];

    if ([DECPARTSTR(f) isEqualToString:@"0"]) return INTPARTSTR(f);
    if ([INTPARTSTR(f) length]==5) return INTPARTSTR(f);

    if ([result length]>5)
    {
        int diff = (int)[result length]-7;

        NSString* newResult = @"";

        for (int i=0; i<[result length]-diff-1; i++)
            newResult = [newResult stringByAppendingFormat:@"%c",[result characterAtIndex:i]];

        return newResult;
    }


    return result;
}

测试:

- (void)awakeFromNib
{
    NSLog(@"%@",[self formatFloat:234.63]);
    NSLog(@"%@",[self formatFloat:1234.65]);
    NSLog(@"%@",[self formatFloat:11234.65]);
    NSLog(@"%@",[self formatFloat:11234]);
}

输出

2012-04-26 19:27:24.429 newProj[1798:903] 234.63
2012-04-26 19:27:24.432 newProj[1798:903] 1234.6
2012-04-26 19:27:24.432 newProj[1798:903] 11234
2012-04-26 19:27:24.432 newProj[1798:903] 11234

答案 2 :(得分:0)

以下是我在代码中实现此操作的方法。我不知道它有多高效,我希望不错。

所以我创建了一个全局的NSNumberFormatter

NSNumberFormatter* numFormatter; 

并在某处初始化它:

numFormatter=[[NSNumberFormatter alloc]init];

然后我使用以下函数格式化数字:

- (NSString*)formatFloat:(Float32)number withOptimalDigits:(UInt8)optimalDigits maxDecimals:(UInt8)maxDecimals
{
    NSString* result;
    UInt8 intDigits=(int)log10f(number)+1;
    NSLog(@"Formatting %.5f with maxDig: %d maxDec: %d intLength: %d",number,optimalDigits,maxDecimals,intDigits);  

    numFormatter.maximumFractionDigits=maxDecimals;
    if(intDigits>=optimalDigitis-maxDecimals) {
        numFormatter.usesSignificantDigits=YES;
        numFormatter.maximumSignificantDigits=(intDigits>optimalDigits)?intDigits:optimalDigits;
    } else {
        numFormatter.usesSignificantDigits=NO;
    }
    result = [numFormatter stringFromNumber:[NSNumber numberWithFloat:number]];

    return result;
}

答案 3 :(得分:0)

在iOS 8上maximumFractionDigits上同时使用maximumSignificantDigitsNSNumberForamtter时,这是一个错误吗?

        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        formatter.maximumFractionDigits = 2;  
        formatter.maximumSignificantDigits = 3;
        NSLog(@"%@", [formatter stringFromNumber:@(0.3333)]); // output 0.333 expected 0.33

如果我只使用maximumFractionDigits

,它可以正常工作
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        formatter.maximumFractionDigits = 2;
        NSLog(@"%@", [formatter stringFromNumber:@(0.3333)]); // output expected .33

NSNumberFormatter maximumFractionDigits and maximumSignificantDigits bug