Nsnumberformatter:Show 'K' Instead of ',000' in Large Numbers

NSNumberFormatter : Show 'k' instead of ',000' in large numbers?

edit/update

Swift 3 or later

extension FloatingPoint {
var kFormatted: String {
return String(format: self >= 1000 ? "$%.0fK" : "$%.0f", (self >= 1000 ? self/1000 : self) as! CVarArg )
}
}

The you can use it like this to format your output:

10.0.kFormatted     // "$10"
100.0.kFormatted // "$100"
1000.0.kFormatted // "$1K"
10000.0.kFormatted // "$10K"
162000.0.kFormatted // "$162K"
153000.0.kFormatted // "$153K"
144000.0.kFormatted // "$144K"
135000.0.kFormatted // "$135K"
126000.0.kFormatted // "$126K"

NSNumberFormatter only display E for large/small values?

I don't claim to be an NSNumberFormatter expert - there are too many options to remember. But setting zeroSymbol seems to solve your problem:

measurementFormatter.zeroSymbol = "0"

Edit: I have spent too much time over this tonight. It seems like there no way to get rid of those E0, so I decided to subclass NSNumberFormatter instead:

class MyNumberFormatter: NSNumberFormatter {
override func stringFromNumber(number: NSNumber) -> String? {
guard let str = super.stringFromNumber(number) else {
return nil
}
return str.stringByReplacingOccurrencesOfString("E0", withString: "", options: [.AnchoredSearch, .BackwardsSearch], range: str.startIndex..<str.endIndex)
}
}

var measurementFormatter = MyNumberFormatter()
measurementFormatter.locale = NSLocale.currentLocale()
measurementFormatter.numberStyle = .ScientificStyle
measurementFormatter.alwaysShowsDecimalSeparator = true
measurementFormatter.minimumFractionDigits = 0
measurementFormatter.maximumFractionDigits = 6
measurementFormatter.generatesDecimalNumbers = false

// Examples:
[0, 0.0014, 2, 15, 3.14, 100, 1500000000].forEach {
print("\($0) --> \(measurementFormatter.stringFromNumber($0)!)")
}

Output:

0 --> 0
0.0014 --> 1.4E-3
2 --> 2
15 --> 1.5E1
3.14 --> 3.14
100 --> 1E2
1500000000 --> 1.5E9

iOS convert large numbers to smaller format

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!

Swift how to format a large number with thousands separators?

Swift Xcode 6.3, SOLVED (I decided to leave the $ in the code). If you don't want a $ in the output, change .CurrencyStyle to .DecimalStyle

var fv = 3534234.55 
var formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
formatter.maximumFractionDigits = 0;
resultFV.text = formatter.stringFromNumber(fv) // result: $3,534,235 –

NSNumberFormatter with number style NSNumberFormatterCurrencyStyle trouble with commas

Each Locale determines if it shows cents or just Krona. So, if you want to force it to show digits after the comma, add the line:

[numberFormatter setMinimumFractionDigits:2];

to get two digits after comma.

But the example you show has correct output.

Formatting input for currency with NSNumberFormatter in Swift

Here's an example on how to use it on Swift 3.
( Edit: Works in Swift 5 too )

let price = 123.436 as NSNumber

let formatter = NumberFormatter()
formatter.numberStyle = .currency
// formatter.locale = NSLocale.currentLocale() // This is the default
// In Swift 4, this ^ was renamed to simply NSLocale.current
formatter.string(from: price) // "$123.44"

formatter.locale = Locale(identifier: "es_CL")
formatter.string(from: price) // $123"

formatter.locale = Locale(identifier: "es_ES")
formatter.string(from: price) // "123,44 €"

Here's the old example on how to use it on Swift 2.

let price = 123.436

let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
// formatter.locale = NSLocale.currentLocale() // This is the default
formatter.stringFromNumber(price) // "$123.44"

formatter.locale = NSLocale(localeIdentifier: "es_CL")
formatter.stringFromNumber(price) // $123"

formatter.locale = NSLocale(localeIdentifier: "es_ES")
formatter.stringFromNumber(price) // "123,44 €"

NSNumberFormatter from 13000 to 13K

The 'K' suffix is not recognized as standard, so you can't do this using NSNumberFormatter.
anyway this is a simple way to do that.

-(NSString *)kFormatForNumber:(int)number{
int result;
if(number >= 1000){
result = number/1000;

NSString *kValue = [NSString stringWithFormat:@"%dk",result];
return kValue;
}
return [NSString stringWithFormat:@"%d",number];
}

How do I set NSNumberFormatter to display numbers using 万 (Japanese/Chinese 10,000 marker)?

EDIT: Up to date gist here: https://gist.github.com/fjolnir/cd72ea39be1476023adf

Old thread, but I came across it while looking for a solution so I figured I'd post my implementation.

The formatter itself does not handle placement of 円, but that's easy to do outside of it. (as the example below demonstrates)

The expected output of the below is:

2015-03-11 18:00:13.376 LENumberFormatter[82736:3604947] 12億3,460万円
2015-03-11 18:00:13.377 LENumberFormatter[82736:3604947] 25円

-

@import Foundation;
@import ObjectiveC.message;

typedef NS_ENUM(NSUInteger, LENumberFormatterAbbreviationStyle) {
kLEAbbreviateShort, // 2.5m
kLEAbbreviateNormal // 2m 5k
};

@interface LENumberFormatter : NSNumberFormatter
@property(nonatomic) BOOL abbreviateLargeNumbers;
@property(nonatomic) LENumberFormatterAbbreviationStyle abbreviationStyle;
@end


@implementation LENumberFormatter
- (instancetype)init
{
if((self = [super init])) {
self.abbreviationStyle = [self _usingKanjiNumbers]
? kLEAbbreviateNormal
: kLEAbbreviateShort;
}
return self;
}

- (NSString *)stringForObjectValue:(id const)aObj
{
if(!_abbreviateLargeNumbers || ![aObj isKindOfClass:[NSNumber class]])
return [super stringForObjectValue:aObj];

// Copy ourselves to get format the partial digits using the settings on self
LENumberFormatter * const partialFormatter = [self copy];
partialFormatter.currencySymbol = @"";
if(_abbreviationStyle == kLEAbbreviateNormal)
partialFormatter.maximumFractionDigits = 0;

NSString *(^partialFormat)(NSNumber*) = ^(NSNumber *num) {
NSString *(*superImp)(struct objc_super*,SEL,NSNumber*) = (void*)&objc_msgSendSuper;
return superImp(&(struct objc_super) { partialFormatter, self.superclass }, _cmd, num);
};

double n = [aObj doubleValue];
BOOL const shortFormat = _abbreviationStyle == kLEAbbreviateShort;

NSDictionary * const separators = [self _localizedGroupingSeparators];
NSArray * const separatorExponents = [separators.allKeys sortedArrayUsingSelector:@selector(compare:)];

BOOL const currencySymbolIsSuffix = [self.positiveFormat hasSuffix:@"¤"];
NSMutableString * const result = currencySymbolIsSuffix || self.numberStyle != NSNumberFormatterCurrencyStyle
? [NSMutableString new]
: [self.currencySymbol mutableCopy];
NSUInteger significantDigits = 0;
NSNumber *lastExp = nil;
for(NSNumber *exp in separatorExponents.reverseObjectEnumerator) {
double divisor = pow(10, exp.shortValue);
if(divisor > n)
continue;

if(lastExp)
significantDigits += lastExp.doubleValue - exp.doubleValue;
lastExp = exp;

if(self.usesSignificantDigits && significantDigits >= self.maximumSignificantDigits)
break;

double partialNum = shortFormat
? n/divisor
: floor(n/divisor);
NSString * const digits = [self _groupRecursively] && ![exp isEqual:@0]
? [partialFormatter stringFromNumber:@(partialNum)]
: partialFormat(@(partialNum));
[result appendFormat:@"%@%@", digits, separators[exp]];

n = fmod(n, divisor);

if(shortFormat)
break; // Just use a float+first hit

// If we make it here, partialNum is integral and we can use log10 to find the number of digits
significantDigits += log10(partialNum) + 1;
partialFormatter.maximumSignificantDigits -= digits.length;

}
if(n > 0
&& !shortFormat
&& (!self.usesSignificantDigits || significantDigits < self.maximumSignificantDigits))
{
partialFormatter.maximumFractionDigits = self.maximumFractionDigits;
[result appendString:partialFormat(@(n))];
}
if(self.numberStyle == NSNumberFormatterCurrencyStyle && currencySymbolIsSuffix && self.currencySymbol)
[result appendString:self.currencySymbol];

return result.length > 0
? [result stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]
: [super stringForObjectValue:aObj];
}

- (BOOL)_usingKanjiNumbers
{
return [self.locale.localeIdentifier rangeOfString:@"^(ja|zh)_"
options:NSRegularExpressionSearch].location != NSNotFound;
}
- (NSDictionary *)_localizedGroupingSeparators
{
if(self._usingKanjiNumbers)
return @{ @2: @"百", @3: @"千", @4: @"万", @8: @"億" };
else {
NSBundle * const bundle = [NSBundle bundleForClass:self.class];
return @{
@3: [bundle localizedStringForKey:@"thousandSuffix" value:@"k " table:nil],
@6: [bundle localizedStringForKey:@"millionSuffix" value:@"m " table:nil]
};
}
}

- (BOOL)_groupRecursively
{
// Return _usingKanjiNumbers if you want:
// 12億3千4百56万7千8百90
// Rather than:
// 1億2,3456万7千8百90
return NO;
}

- (instancetype)copyWithZone:(NSZone * const)aZone
{
LENumberFormatter * const copy = [super copyWithZone:aZone];
copy.abbreviateLargeNumbers = _abbreviateLargeNumbers;
copy.abbreviationStyle = _abbreviationStyle;
return copy;
}
@end


int main(int argc, char *argv[]) {
@autoreleasepool {
LENumberFormatter * const f = [LENumberFormatter new];
f.locale = [NSLocale localeWithLocaleIdentifier:@"ja_JP"];
// f.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
f.numberStyle = NSNumberFormatterCurrencyStyle;
f.abbreviateLargeNumbers = YES;
f.abbreviationStyle = kLEAbbreviateNormal; // Automatic if using system locale
f.maximumSignificantDigits = 5;
f.usesSignificantDigits = YES;
// f.currencyCode = @"JPY";
// f.currencySymbol = @"¥";

if([f.locale.localeIdentifier hasPrefix:@"ja"]) {
f.positiveFormat = @"#,##0¤";
if([f.currencyCode isEqualToString:@"JPY"])
// We allow ourselves this special case because *日本円 just looks dumb
f.currencySymbol = @"円";
else
f.currencySymbol = [f.locale displayNameForKey:NSLocaleCurrencyCode
value:f.currencyCode];
}

NSLog(@"%@", [f stringFromNumber:@1234567890]);
NSLog(@"%@", [f stringFromNumber:@25]);
}
}

NSNumberFormatter currency negative number

You have to set the negative format.
Add this line:

[f setNegativeFormat:@"-¤#,##0.00"];

but maybe you just want to set the locale with [f setLocale:] instead of setting every format option on your own.

(and next time post code that does compile.)



Related Topics



Leave a reply



Submit