iosformattingnsnumberdata-conversionhuman-readable

iOS convert large numbers to smaller format


How can I convert all numbers that are more than 3 digits down to a 4 digit or less number?

This is exactly what I mean:

10345 = 10.3k
10012 = 10k
123546 = 123.5k
4384324 = 4.3m

Rounding is not entirely important, but an added plus.

I have looked into NSNumberFormatter but have not found the proper solution, and I have yet to find a proper solution here on SO. Any help is greatly appreciated, thanks!


Solution

  • Here are two methods I have come up with that work together to produce the desired effect. This will also automatically round up. This will also specify how many numbers total will be visible by passing the int dec.

    Also, in the float to string method, you can change the @"%.1f" to @"%.2f", @"%.3f", etc to tell it how many visible decimals to show after the decimal point.

    For Example:
    
    52935 --->  53K
    52724 --->  53.7K
    
    
    
    
    
    -(NSString *)abbreviateNumber:(int)num withDecimal:(int)dec {
    
        NSString *abbrevNum;
        float number = (float)num;
    
        NSArray *abbrev = @[@"K", @"M", @"B"];
    
        for (int i = abbrev.count - 1; i >= 0; i--) {
    
            // Convert array index to "1000", "1000000", etc
            int size = pow(10,(i+1)*3);
    
            if(size <= number) {
                // Here, we multiply by decPlaces, round, and then divide by decPlaces.
                // This gives us nice rounding to a particular decimal place.
                number = round(number*dec/size)/dec;
    
                NSString *numberString = [self floatToString:number];
    
                // Add the letter for the abbreviation
                abbrevNum = [NSString stringWithFormat:@"%@%@", numberString, [abbrev objectAtIndex:i]];
    
                NSLog(@"%@", abbrevNum);
    
            }
    
        }
    
    
        return abbrevNum;
    }
    
    - (NSString *) floatToString:(float) val {
    
        NSString *ret = [NSString stringWithFormat:@"%.1f", val];
        unichar c = [ret characterAtIndex:[ret length] - 1];
    
        while (c == 48 || c == 46) { // 0 or .
            ret = [ret substringToIndex:[ret length] - 1];
            c = [ret characterAtIndex:[ret length] - 1];
        }
    
        return ret;
    }
    

    Hope this helps anyone else out who needs it!