NSNumberFormatter glitch - ios

I have a strange problem. It only seems to present on a tester's iPhone 5s.
It works correctly on an iPhone 5, 6 and 6 plus, all running the latest iOS (8.3).
This is the code
-(NSString *) commaString:(double)number
{
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
[numberFormatter setGroupingSize:3];
[numberFormatter setMaximumSignificantDigits:9];
NSString *numberAsString = [numberFormatter stringFromNumber:[NSNumber numberWithDouble: number]];
return numberAsString;
}
The application is a calculator and is usually presenting correctly like this
It is usually showing correctly like this
but on this iPhone 5s it is showing like this
I thought the setMaximumSignificantDigits would have nipped this in the bud, but it's still showing the same. Could this be some strange localisation thing? I don't think it is as his iPhone 6 it is showing correctly also.
Thanks
Luke

If your goal is to simply have commas every three characters, all you need to do is:
NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber * numberFromString = [numberFormatter numberFromString:currentTextWithoutCommas];
NSString * formattedNumberString = [numberFormatter stringFromNumber:numberFromString];
If you're finding that there's an issue with localizing the formatter, then set secondaryGroupingSize to 3. As written in the docs for NSNumberFormatter:
Some locales allow the specification of another grouping size for larger numbers. For example, some locales may represent a number such as 61, 242, 378.46 (as in the United States) as 6,12,42,378.46. In this case, the secondary grouping size (covering the groups of digits furthest from the decimal point) is 2.
Also, you can check out Formatting Numbers on iOSDeveloperTips for a brief, high-level overview.

Related

NSNumberFormatter for 2 Decimal Places

I have some amount that i want to Display in local Style.
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc]init];
numberFormatter.locale = [NSLocale currentLocale];
numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
numberFormatter.usesGroupingSeparator = YES;
NSString* amountText = [NSString stringWithFormat:#"ab %#€",[numberFormatter stringFromNumber:someDoubleNumber]];
Problem is that this is also displaying the currency and that is something that i don't want. Basically what i am looking for is displaying that decimal should be according to local Style with 2 numbers after decimal for example 0.00 or in germany 0,00 with my code i am achieveing this requirement but i am also getting the additionally the currency symbol which i don't want.
Anybody still looking for an answer i achieved it by
[numberFormatter setCurrencySymbol:#""];

NSNumberFormatter with number style NSNumberFormatterCurrencyStyle trouble with commas

I'm trying to do things right with input expenses on some items. So, when working on a device using a locale that uses comma separated decimals (the decimal pad automatically sets comma ',' instead of dot '.' for the user to input) I store the value using core data in a double variable converting the text this way:
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
[f setMaximumFractionDigits:2];
NSNumber * gasto = [f numberFromString:(((UITextField*) [cell viewWithTag:11]).text)];
destino.nuevaTrans.gasto = [gasto doubleValue];
//destino.nuevaTrans is the managed object, nothing weird there, just storing the decimal value
But when taking the value out of the stored objects and showing them in a table view I'm losing the decimals because of the comma separated locale settings (?). Doing it this way:
etiq = (UILabel*) [cell.contentView viewWithTag:12];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
etiq.text = [numberFormatter stringFromNumber:#(trans.gasto)];
//debugging console output:
//remmember, trans.gasto is only a double
NSLog(#"a: %f, b: %#", trans.gasto ,[numberFormatter stringFromNumber:#(trans.gasto)]);
The output on the simulator that is using dot '.' locale settings works fine, but when deploying on the device that is using comma ',' settings the NSNumberFormatter doesn't seem to translate it correctly to currency style.
//output on the simulator:
2014-09-07 15:00:47.561 iSpend[3930:60b] a: 2.990000, b: $2.99
//output on the device:
2014-09-07 15:02:40.005 iSpend[1389:60b] a: 2.170000, b: ₡2
So, I could try and hack this thing out... But I'm looking for a better programming practice here. Every suggestion is appreciated! Thanks!
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.
u can try to set separator clearly: [formatter setDecimalSeparator:#"."];

NSNumberFormatterCurrencyStyle Driving me insane

I'm trying to get a currency calculator to work, and I've stumbled accross a problem I do not know how to solve.
The problem is that when I normally type into the textfield I can obviously type over the 100.20, the problem arises when I try to do this using buttons.
Whole numbers work fine but as soon as I click on the dot button it put's the dot after the 100.20 so I end up with 100.20. and whatever I click after it.
If I don't use NSNumberFormatter it works fine as well.
Here are the code snippets :
-(IBAction)buttonDigitPressed:(id)sender
{
mainNumber = 100.20;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle];
mainField.stringValue = [numberFormatter stringFromNumber:[NSNumber numberWithFloat: mainNumber]];
}
if(!userInTheMiddleOfEnteringDecimal)
{
userInTheMiddleOfEnteringDecimal = YES;
mainField.stringValue= [mainField.stringValue stringByAppendingString:#"."];
}

NSNumberFormatter numberFromString decimal number

I'm trying to parse a NSString with a NSNumberFormatter like following.
NSNumberFormatter *myFormatter = [[[NSNumberFormatter alloc] init];
NSNumber *myNumber = [myFormatter numberFromString:#"42.00000"];
numberFromString returns a NSNumber object in the simulator but not on a device.
The decimals (.00000) are causing the return value to be nil on a device because parsing 42 (without the decimals) works just fine (both in the simulator and on a device).
The reason I'm using a NSNumberFormatter is because is like how it returns nil if the string is not a valid number (which is working against me here :p). NSString doubleValue does not provide this kind of behaviour. Also, NSDecimalNumber decimalNumberWithString doesn't do the job because [NSDecimalNumber decimalNumberWithString:#"4a2.00000"] returns 4.
Any ideas why this would not work on a device?
Is it the locale? I tried setting myFormatter.numberStyle = NSNumberFormatterNoStyle and NSNumberFormatterDecimalStyle but it changes nothing.
As #rmaddy already said in a comment, the decimal separator of NSNumberFormatter is
locale dependent. If you have a fixed input format with the dot as decimal separator,
you can set the "POSIX locale":
NSNumberFormatter *myFormatter = [[NSNumberFormatter alloc] init];
[myFormatter setLocale:[NSLocale localeWithLocaleIdentifier:#"en_US_POSIX"]];
NSNumber *myNumber = [myFormatter numberFromString:#"42.00000"];
Alternatively, you can use NSScanner to parse a double value, as e.g. described
here: parsing NSString to Double
42.00000 is not a string mate, why not #"42.00000"?

Converting double to string return strange value in objective c

I have an NSDictionary which consist of multiple key/pair values. One of them consist double value.
NSNumber *goalValue = [info objectForKey:#"goalValue"];
I put breakpoint and I found that goalValue store the normal value that I need.
and just below I convert it to NSSting like
NSString *stringValue=[goalValue stringValue];
and this stringValue store very strange value.
Guys please help me. I am totally puzzled, I did goggle but nothing change. Please help me. Thanks in advance.
The method stringValue will convert the NSNumber to string by internally calling descriptionWithLocale: with locale as nil and this method in turn will call initWithFormat:locale:,
From Apple docs,
To obtain the string representation, this method invokes NSString’s initWithFormat:locale: method, supplying the format based on the type the NSNumber object was created with:
So format specifier used for double is %0.16g(i.e. 16 digit precision) hence the value 98.09999999999999
I'd suggest using NSNumberFormatter,
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:2]; //2 decimal places, change this as required.
NSString *string = [numberFormatter stringFromNumber:goalValue];
Hope that helps!
To prevent this behavior, I suggest using NSDecimalNumber (also this is from my experience best format when dealing with very precise amounts)
NSDecimalNumber *doubleDecimal = [[NSDecimalNumber alloc] initWithDouble:[info objectForKey:#"goalValue"]];
for two digits formatting, use numberFormatter
NSNumberFormatter * nf = [[NSNumberFormatter alloc] init];
[nf setMinimumFractionDigits:2];
[nf setMaximumFractionDigits:2];
NSString *stringValue = [nf stringFromNumber:doubleDecimal]
Its showing the rounded value so you can round the value to single digit using NSNumberFormatter.
NSNumberFormatter *fomatter = [[NSNumberFormatter alloc] init];
[fomatter setMaximumSignificantDigits:2];
NSString *stringValue=[fomatter stringFromNumber:goalValue];

Resources