Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limiting both the fractional and total number of digits when formatting a float for display

I need to print a float value in area of limited width most efficiently. I'm using an NSNumberFormatter, and I set two numbers after the decimal point as the default, so that when I have a number like 234.25 it is printed as is: 234.25. But when I have 1234.25 I want it to be printed as: 1234.3, and 11234.25 should be printed 11234.

I need a maximum of two digits after the point, and a maximum of five digits overall if I have digits after the point, but it also should print more than five digits if the integer part has more.

I don't see ability to limit the total number of digits in NSNumberFormatter. Does this mean that I should write my own function to format numbers in this way? If so, then what is the correct way of getting the count of digits in the integer and fractional parts of a number? I would also prefer working with CGFLoat, rather than NSNumber to avoid extra type conversions.

like image 734
BartoNaz Avatar asked Apr 26 '12 16:04

BartoNaz


Video Answer


2 Answers

You're looking for a combination of "maximum significant digits" and "maximum fraction digits", along with particular rounding behavior. NSNumberFormatter is equal to the task:

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]]);

Result:

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

like image 85
jscs Avatar answered Sep 20 '22 06:09

jscs


Code :

#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;
}

Testing it :

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

Output :

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
like image 33
Dr.Kameleon Avatar answered Sep 19 '22 06:09

Dr.Kameleon