views:

317

answers:

3

I have a distance as a float and I'm looking for a way to format it nicely for human readers. Ideally, I'd like it to change from m to km as it gets bigger, and to round the number nicely. Converting to miles would be a bonus. I'm sure many people have had a need for one of these and I'm hoping that there's some code floating around somewhere.

Here's how I'd like the formats:

  • 0-100m: 47m (as a whole number)
  • 100-1000m: 325m or 320m (round to the nearest 5 or 10 meters)
  • 1000-10000m: 1.2km (round to nearest with one decimal place)
  • 10000m +: 21km

If there's no code available, how can I write my own formatter?

Thanks

+2  A: 

Yes you need to write your own formatter, like

#include <math.h>
NSString* convertDistanceToString(float distance) {
    if (distance < 100)
       return [NSString stringWithFormat:@"%g m", roundf(distance)];
    else if (distance < 1000)
       return [NSString stringWithFormat:@"%g m", roundf(distance/5)*5];
    else if (distance < 10000)
       return [NSString stringWithFormat:@"%g km", roundf(distance/100)/10];
    else
       return [NSString stringWithFormat:@"%g km", roundf(distance/1000)];
}
...
NSLog(@"The distance is %@", convertDistanceToString(1024));
KennyTM
Thanks very much for the answer, this was perfect for what I needed (and saved me lots of time).
nevan
+1  A: 

Here's how I do it. This uses the locale of the user to properly format the string, which you should probably do too.

// Returns a string representing the distance in the correct units.
// If distance is greater than convert max in feet or meters, 
// the distance in miles or km is returned instead
NSString* getDistString(float distance, int convertMax, BOOL includeUnit) {
  NSString * unitName;
  if (METRIC) {
    unitName = @"m";
    if (convertMax != -1 && distance > convertMax) {
      unitName = @"km";
      distance = distance / 1000;
    }
  } else {
    unitName = @"ft";
    if (convertMax != -1 && distance > convertMax) {
      unitName = @"mi";
      distance = distance / 5280;
    }
    distance = metersToFeet(distance);
  }

  if (includeUnit) return [NSString stringWithFormat:@"%@ %@", formatDecimal_1(distance), unitName];

  return formatDecimal_1(distance);

}
// returns a string if the number with one decimal place of precision
// sets the style (commas or periods) based on the locale
NSString * formatDecimal_1(float num) {
  static NSNumberFormatter *numFormatter;
  if (!numFormatter) {
    numFormatter = [[[NSNumberFormatter alloc] init] retain];
    [numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [numFormatter setLocale:[NSLocale currentLocale]];
    [numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numFormatter setMaximumFractionDigits:1];
    [numFormatter setMinimumFractionDigits:1];
  }

  return [numFormatter stringFromNumber:F(num)];

}
Andrew Johnson
Thanks very much. I hadn't thought of using localization for the number formats. I'll have to take the time to add this to the code I used.
nevan
How do you know if the user wants METRIC or not?
MattDiPasquale
If they don't live in the US, we default to metric. And they can switch it. You can check NSLocale to get their location.
Andrew Johnson
A: 

found this today asking the same question....going with :

 NSString *rvalue;
    if (value > 1000) {
        rvalue = [NSString stringWithFormat:@"%.02f km",value];
    }else {
        rvalue = [NSString stringWithFormat:@"%.02f m",value];
    }

could wrap this in a method, if need be

mlecho