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"?
Related
I saw some code trying to format lat long using the following NSNumberFormatter.
NSNumberFormatter * sut = [[NSNumberFormatter alloc] init];
[sut setMaximumFractionDigits:20]; // also tried set to 15 or 16, not working too.
[sut setMaximumSignificantDigits:20];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc]initWithLocaleIdentifier:#"en_US_POSIX"];
[sut setLocale:enUSPOSIXLocale];
NSString *expected = #"1.299129258067496"; // 16 significants digits
NSString *actual = [sut stringFromNumber:#(1.299129258067496)];
[[actual should] equal:expected];// Failed to pass, the actual is #"1.2991292580675"
Although in this case, we may not need to use the NSNumberFormatter to get the correct result, I'm wondering why NSNumberFormatter only returns string of up to 14 significant digits.
It only shows 14 decimal places because the double type rounds at 15 decimal places. This worked for me because you can set the number of decimal places shown.
[NSString stringWithFormat:#"%.20f", 1.299129258067496]
Just make sure the number of decimal places does not exceed the number otherwise the program makes up numbers to fill the rest. Hope this helps.
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:#"."];
Getting correct localized formatting of numbers to display is easy.
But prompting for a decimal number input from a UITextField is proving tricky.
Even though the decimal keypad may present the comma for European usage instead of the stop, the method handling the input apparently still needs to be locale-savvy.
my research here on S.O. and other places suggests
-(IBAction)buttonPress:(UIButton *)sender
{
NSNumber *firstNumber = #([self.firstField.text floatValue]); // 2 alternative ways
NSNumber *secondNumber = [NSNumber numberWithFloat:[self.secondField.text floatValue]];
.
.
only gives me integers to perform arithmetic with. They aren't floats at all. They have no float value
Supposing this is the only thing the app does, and I immediately do:
.
.
NSNumberFormatter *numberFormat = [[ NSNumberFormatter alloc] init];
[ numberFormat setNumberStyle:NSNumberFormatterDecimalStyle];
[ numberFormat setLocale:[NSLocale currentLocale]];
[ numberFormat setMaximumFractionDigits:2];
NSString *displayString = [ numberFormat stringFromNumber:firstNumber];
self.resultLabel.text = displayString;
}
I am throwing the input back to a label in the ViewController without any further handling to make sure the the decimals aren't hidden by not having a formatter. No Joy. Still in integers.
Obviously the app has to do something in the way of calculation, and since one can't handle NSNumber wrappers directly, I have to resolve it before i do the conversion thing:
double xD = [firstNumber doubleValue];
double yD = [secondNumber doubleValue];
the question is, where is the decimal-ness of the input being lost?
I have no problem with the desktop keyboard and the simulator, but if i set a test device to - say - Polish then that simply won't do.
EDIT:
and here's the result from the answer provided below
// run these 4 methods first, that way you can re-use *numberFormat for the display
NSNumberFormatter *numberFormat = [[ NSNumberFormatter alloc] init];
[ numberFormat setNumberStyle:NSNumberFormatterDecimalStyle];
[ numberFormat setLocale:[NSLocale currentLocale]];
[ numberFormat setMaximumFractionDigits:2];
// here 'tis
NSNumber *firstNumber = [numberFormat numberFromString:self.firstField.text];
// do the same for other input UITextFields
// sh-boom. there you go
You need use longLongValue not longValue to convert NSString to long type. or use NSNumberFormatter->numberFromString:
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];
what is the best way on how to deal with integers, NSStrings and NSNumberFormatter ?
I have an app with an UITextField, where users can input numbers. By every change in the UITextField, my app is immediately taking the input, put it in my function that makes a calculation, and outputs the result in an UILabel.
people can work with large numbers here, so in order to make it easier for them to read what their input is, I decided that I want to make it possible so that the input changes as soon as they insert it.
For example, when you type in 1000 that it automatically changes into 1,000. when you type in 100000000000 it automatically changes into 100,000,000,000 etc.
This I was able to do myself, like this:
formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
self.inputField.text = [formatter stringFromNumber:[formatter numberFromString:self.inputField.text]];
maybe not the best way, but it works.
my function expects an int as input, so up till 999 it's very easy: i can do the following:
[self.inputField.text integerValue];
and it works
but whenever I have 1000 or higher in my UITextField, self.inputField.text property will be 1,000 .. and then things go wrong with using the integerValue from it.
So my question is, how can I go back from NSString to an int, when there are decimals in it ?
Use the -numberFromString function to get an NSNumber from the string, then use the intValue from the NSNumber class to get the integer value:
NSString *string = #"1,000";
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *number = [formatter numberFromString:string];
int intValue = [number integerValue];// intValue = 1000