Differing NSNumberFormatter behavior - iphone

Consider this code:
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterCurrencyStyle;
NSLocale *l = [[NSLocale alloc] initWithLocaleIdentifier:#"it_IT"];
nf.locale = l;
[l release];
nf.decimalSeparator = #",";
nf.currencySymbol = #"US$";
[nf setLenient:YES];
NSString *s = #"US$ 0,05";
double d = [[nf numberFromString:s] doubleValue];
NSLog(#"%.2f",d);`
If I execute this in a normal Cocoa console-based application (10.6 sdk), I get the output "0.05" to the debug console.
However, if I execute this in the iPhone environment (OS 3.1.3), I get "0.00" output to the debug console. Am I doing something wrong with my usage of NSNumberFormatter? Or is this a discrepancy between the two platforms?

NSString *s = #"US$ 0,05";
What if you remove the space?

Related

Obj-C Help on code to convert number (no known class method for selector)

Newbie on Obj-C here : )
I'm writing a code that converts numbers (mostly to control the zeros after the dot, 5.000 -> 5 or 5.00).
So, I got it to work but I really wanted to create a class to use it as I need.
Here is the working code:
MainViewController.h
currentNumber = currentNumber *10 + (float)[sender tag];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:0];
NSString *convertedNumber = [formatter stringFromNumber:[NSNumber numberWithFloat:currentNumber]];
calculatorScreen.text = [NSString stringWithFormat:#"%#",convertedNumber];
So, I just want to create a class that will do that for me and return the convertedNumber.
Here what I have done:
FormatNumber.h
#interface FormatNumber: NSNumber
{
NSString *nf;
}
- (void) getNumber:(float)n1;
- (NSString *) retNumber;
#end
FormatNumber.m
#implementation FormatNumber;
-(void) getNumber:(float)n1
{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:0];
nf = [formatter stringFromNumber:[NSNumber numberWithFloat: n1]];
}
-(NSString *) retNumber; // As I cannot return something from void, I tried to do this way, don't know if it's the better
{
return nf;
}
#end
MainViewController.h (trying to pass and get the value from the class)
currentNumber = currentNumber *10 + (float)[sender tag];
NSString *convertedNumber = 0;
FormatNumber *n1 = [[FormatNumber alloc] init];
[FormatNumber getNumber:currentNumber]; // No known class method for selector 'getNumber'
convertedNumber = [FormatNumber retNumber]; // No known class method for selector 'retNumber'
calculatorScreen.text = [NSString stringWithFormat:#"%#",convertedNumber];
Also, if there is a simple way to write this code I would appreciate some insights : )
You can do it by using C-way, use %.2f(for 2 decimals) and/or %.4f(for four decimals) and %.0 for no decimal.
Here is a sample code for this.
float f=5.0000;
NSLog(#"res: %.2f", f); //5.00
NSLog(#"res: %.0f", f); //5

Display an integer with a comma: 30000 --> 30,000

How do I display an integer within a UILabel with a comma?
Like this:
30000 --> 30,000
My English is not that good so I did not know what to search for.
Thank you for your answers.
Use the NSNumberFormatter and do just few things as :
NSInteger integerValue=30000;
NSNumberFormatter *numberFormatterComma = [NSNumberFormatter new];
[numberFormatterComma setNumberStyle:NSNumberFormatterDecimalStyle];
NSString *formatted = [numberFormatterComma stringFromNumber:[NSNumber numberWithInteger:integerValue]];
NSLog(#"--> %#",formatted);
Now you can put the formatted string to your label.
You want to look at NSNumberFormatter
Here is an example
self.numberFormat = [[NSNumberFormatter alloc] init];
//set up formatter for display text
[self.numberFormat setNumberStyle:NSNumberFormatterDecimalStyle];
[self.numberFormat setRoundingMode:NSNumberFormatterRoundFloor];
[self.numberFormat setMinimumFractionDigits:0];
[self.numberFormat setMinimumIntegerDigits:1];
[self.numberFormat setMaximumFractionDigits:24];
[self.numberFormat setMaximumSignificantDigits:24];
NSString* formattedText =
[self.numberFormat stringFromNumber:[self.numberFormat numberFromString:rawString]];
Take care not to alloc/init them often, they are quite heavy objects. Best to create once and keep in a property for reuse. If you are making OSX apps (as opposed to ios) you get formatting objects in Interface Builder also, you can drag them around and set their parameters in the attributes inspector.
// Comma seperated numeric conversion
-(NSString*)convertNumericIntoCommaSeperatedValue:(NSString*)string{
NSNumberFormatter *frmtr = [[NSNumberFormatter alloc] init];
[frmtr setGroupingSize:3];
[frmtr setGroupingSeparator:#","];
[frmtr setUsesGroupingSeparator:YES];
NSString *commaSeperatedString = [frmtr stringFromNumber:[NSNumber numberWithLongLong:[string longLongValue]]];
[frmtr release],frmtr=nil;
return commaSeperatedString;
}

Number formatting

Hi all I am using below method to get string from NSNumber
-(NSString *)stringFromNumber:(NSNumber *)number
{
NSLog(#"Input:---%#",number);
NSNumberFormatter *numFormatter = [[[NSNumberFormatter alloc] init] autorelease];
[numFormatter setMaximumFractionDigits:5];
[numFormatter setMinimumFractionDigits:2];
//[numFormatter setExponentSymbol:#"e"];
NSString *str_num = [numFormatter stringFromNumber:number];
NSLog(#"Output:---%#",str_num);
return str_num;
}
in console i am getting like below
Input:---2.940000057220459
Output:---2.94
Input:---2940.000057220459
Output:---2940.00006
Input:---2.940000057220459e-15
Output:---.00
Input:---2.940000057220459e-12
Output:---.00
Input:---2.940000057220459e-09
Output:---.00
Input:---2.940000057220459e-06
Output:---.00
Input:---0.002940000057220459
Output:---.00294
but I need the output to look like below for above inputs (order)
---2.94
---2940
---2.94e-15
---2.94e-12
---2.94e-6
---2.94e-9
---0.00294
How would I do it? Someone please help me.
i tried this
-(NSString *)stringFromNumber:(NSNumber *)number
{
NSLog(#"Input:---%#",number);
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setMaximumFractionDigits:5];
[numFormatter setMinimumFractionDigits:2];
NSString *temp = [NSString stringWithFormat:#"%#",number];
NSRange range = [temp rangeOfString:#"e"];
if(range.length > 0){
[numFormatter setNumberStyle:NSNumberFormatterScientificStyle];
[numFormatter setExponentSymbol:#"e"];
}
NSString *str_num = [numFormatter stringFromNumber:number];
NSLog(#"Output:---%#",str_num);
return str_num;
}
and Got like this
Input:---2.940000057220459
Output:---2.94
Input:---2940.000057220459
Output:---2940.00006
Input:---2.940000057220459e-15
Output:---2.94e-15
Input:---2.940000057220459e-12
Output:---2.94e-12
Input:---2.940000057220459e-09
Output:---2.94e-9
Input:---2.940000057220459e-06
Output:---2.94e-6
Input:---0.002940000057220459
Output:---.00294
Take a look at NSNumberFormatter Class.
setMinimumFractionDigits:
setMinimumIntegerDigits:

Showing formatted digits in textField iphone application

I am taking data from XMl file, the distance in xml is like
<distance>13.472987570222 km</distance>
Now i want to show just two digits after . operator. i.e i want to show in textField like 13.47 km. i have saved this distance digits in NSString *distance;
Thanks
float theDistance = [distance floatValue];
NSString *roundedDistance = [NSString stringWithFormat:#"%.2f",theDistance];
That will round to 2dp. :)
You can use very powerful class NSNumberFormatter:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setPositiveFormat:#"##0.## km"];
[numberFormatter setNegativeFormat:#"##0.## km"];
NSNumber *number = [NSNumber numberWithDouble:[distance doubleValue]];
NSString *formattedString = [numberFormatter stringFromNumber:number];
For more info read here
Strikes me you should really be converting the xml string into a float or some other such appropriate type and then using a format specifier when displaying the value.

UIKeyboardTypeDecimalPad - change comma to dot

I use this method to show keyboard with decimal separator
myTextField.keyboardType=UIKeyboardTypeDecimalPad;
How can I change comma to dot separator?
I have a Finnish locale. With comma, decimals doesn't work on my app.
-(IBAction)calculate {
float x = ([paino.text floatValue]) / ([pituus.text floatValue]) *10000;
label.text = [[NSString alloc] initWithFormat:#"%0.02f", x];
}
OK so you edit a text field using a numeric keyboard, which is dependent on the current locale, and thus get a text representation of a number, which is dependendt on the current locale, too. After editing has finished you read it and want to transform into a number.
To convert you would use NSNumberFormatter like this:
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
You can setup the formatter as you will, setting locale (!), limits, formatting, decimal/grouping separator, number of decimal digits etc. Then you just use it:
float number = [nf numberFromString: field.text];
And that's all! Now you have the number even if the text includes comma, provided you let both: keyboard and formatter, to have the same format, same style - i.e. probably just let current locale be used all over the place.
EDIT
this is a currency formatter, that can convert between string and number for currencies:
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle: NSNumberFormatterCurrencyStyle];
[nf setRoundingMode: NSNumberFormatterRoundHalfUp];
[nf setMaximumFractionDigits: 2]
this is a percentage formatter with 4 decimal places:
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle: NSNumberFormatterPercentStyle];
[nf setRoundingMode: NSNumberFormatterRoundHalfUp];
[nf setMaximumFractionDigits: 4];
both in the current locale.
As you see you can define the style, digits, rounding behaviour and much more, depending on numbers you are trying to enter. For more details (it is really a lot you can do with the NSNumberFormatter) you should read Apple docs, it would go beyond the scope of SO answer to describe it all.
In your case, provided that paino and pituus are also UITextFields:
-(IBAction)calculate {
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setRoundingMode: NSNumberFormatterRoundHalfUp];
[nf setMaximumFractionDigits: 2];
float npaino = [[nf numberFromString: paino.text] floatValue];
float npituus = [[nf numberFromString: pituus.text] floatValue];
float x = npaino] / npituus *10000;
label.text = [nf stringFromNumber: [NSNumber numberWithFloat: x]];
[nf release];
}
Now to avoid creating the formatter in each calculation you could make it an instance variable, since you need only one for those conversions.
Easyer that way:
[[yourField text] stringByReplacingOccurrencesOfString:#"," withString:#"."]
It will work in all ways and languages.
In your code, it will be:
-(IBAction)calculate {
float fPaino = [[paino.text stringByReplacingOccurrencesOfString:#"," withString:#"."] floatValue];
float x = fPaino / ([pituus.text floatValue]) *10000;
label.text = [[NSString alloc] initWithFormat:#"%0.02f", x];
}
Something else: are you sure to need an "alloc" for the result? As the label.text contains already its retain/release, you can simply make a [NSString stringWithFormat:#"%0.02f", x]