Actually, decided to chime in with my own answer. This is my routine for generating strings for outputting human sizes from byte counts:
#include <math.h> // for isgreater()
static NSString * MemorySizeString( mach_vm_size_t size )
{
enum
{
kSizeIsBytes = 0,
kSizeIsKilobytes,
kSizeIsMegabytes,
kSizeIsGigabytes,
kSizeIsTerabytes,
kSizeIsPetabytes,
kSizeIsExabytes
};
int sizeType = kSizeIsBytes;
double dSize = (double) size;
while ( isgreater(dSize, 1024.0) )
{
dSize = dSize / 1024.0;
sizeType++;
}
NSMutableString * str = [[NSMutableString alloc] initWithFormat: (sizeType == kSizeIsBytes ? @"%.00f" : @"%.02f"), dSize];
switch ( sizeType )
{
default:
case kSizeIsBytes:
[str appendString: @" bytes"];
break;
case kSizeIsKilobytes:
[str appendString: @"KB"];
break;
case kSizeIsMegabytes:
[str appendString: @"MB"];
break;
case kSizeIsGigabytes:
[str appendString: @"GB"];
break;
case kSizeIsTerabytes:
[str appendString: @"TB"];
break;
case kSizeIsPetabytes:
[str appendString: @"PB"];
break;
case kSizeIsExabytes:
[str appendString: @"EB"];
break;
}
NSString * result = [str copy];
[str release];
return ( [result autorelease] );
}
It works out the correct size by seeing what order of binary magnitude it is, using 1024 as the base (1024 bytes = 1KB, 1024KB = 1MB, etc.). While doing this, it shrinks the input value (using floating-point arithmetic) such that once it's below 1024, it has both a human-readable value and a magnitude specifier. It then generates a string containing the formatted value (no decimal places for bytes, 2 decimal places for any larger magnitude), and inspects the magnitude constant to determine what suffix to attach.