NSString to NSNumber with some decimal separator - objective-c

The app I'm building now has a possibility to "download" text files and get the numbers from there. In the simulator everything works perfectly, but when I tested it on a device it just crashed. After a while I figured out that the problem was with the decimal separators. In that file I used . and the local setting of my iPhone require ,. Example of that string:
Product 1;100.00
Product 2;82.85
Product 3;95.12
//etc...
After changing the the first few . into , I could successfully run the app till it reached the first ., so that's the problem.
I can easily replace all . into , programmatically, BUT I want this app to work in any country with any number format and not limit it to some specific market.
The code I was using to get these numbers:
NSString *fileContents = [[NSUserDefaults standardUserDefaults]objectForKey:theKey];
NSArray *allLinedStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSMutableArray *allStringNormalized = [NSMutableArray array];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
for (int i = 0; i < allLinedStrings.count; i++) {
NSString *bla = [allLinedStrings objectAtIndex:i];
NSArray *bla1 = [bla componentsSeparatedByString:#";"];
[allStringNormalized addObject:[formatter numberFromString:[bla1 objectAtIndex:1]]];
}
self.values = [NSArray arrayWithArray:allStringNormalized];
Any help would be appreciated.
Thank you :)

If I understand the problem correctly, you want NSNumberFormatter to always use . as the decimal separator, regardless of the phone's locale. The solution to this is simple: use the instance methods setDecimalSeparator: and setCurrencyDecimalSeparator: of NSNumberFormatter to set the decimal separator to ..
Note that you don't need to set both decimal separators. You use setDecimalSeparator: if your numberStyle is NSNumberFormatterDecimalStyle and setCurrencyDecimalSeparator: if your numberStyle is NSNumberFormatterCurrencyStyle.
See the documentation for more details.

Related

NSNumberFormatter Scientific Form Output

I have NSNumber and NSResultFormatter, that converts number into string and displays it on screen.
In scientific form output for large numbers is "1.345e10" and for small numbers is "1.345e-10".
I want to output large numbers as "1.345e+10", like in standart iOS calc app. How can I to do it?
You can achieve that by setting a custom number format, for example:
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setExponentSymbol:#"e"];
[fmt setPositiveFormat:#"0.###E+0"];
NSString *s = [fmt stringFromNumber:#(12345678900)];
// 1.235e+10
Custom number formats are documented in http://www.unicode.org/reports/tr35/tr35-25.html#Number_Format_Patterns.

Convert back localized NSString number (> 4 digits) to integer

I used the localizedStringWithFormat: method on NSString class to convert a seven digit integer number to an NSString somewhere in my code and need to convert it back to an integer now.
As my App is localized for different regions with different separators after three digits (e.g. '.' in the U.S. and ',' in Germany), what's the best way to convert a localized NSString integer value to an integer?
I tried integerValue on my string as follows but it didn't work:
// Somewhere in code:
int num = 1049000;
NSString *myLocalizedNumString = [NSString localizedStringWithFormat:#"%d", num];
// myLocalizedNumString (U.S.): '1,049,000'
// myLocalizedNumString (Germany): '1.049.000'
// Somewhere else where I have a reference to my string but none to the num:
int restoredNum = [myLocalizedNumString integerValue];
// restoredNum isn't 1049000 (it's 0, the initial value)
What would be a good working way of doing it?
Despite its name NSNumberFormatter converts both ways, it is also a string parser. Using the method numberFromString after setting the number formatter’s numberStyle property to NSNumberFormatterDecimalStyle solves your problem.
The code might look as follows:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
NSInteger restoredNum = [[formatter numberFromString:myLocalizedNumString] integerValue];

NSNumberFormatter: string to Double

I am trying to take a user input from a text field and format it into a double value for core data. Currently my code looks like:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *weightDouble = [numberFormatter numberFromString:#"weight.text"];
However, if I print weightDouble I get 0, if I print out the text from the UI input I get the correct number. Any ideas on what I am doing wrong here? I get no errors on the build and it operates and saves fine (other than saving 0 no matter the input)
First of all:
(If 'weight' is a UITextField)
NSNumber *weightDouble = [numberFormatter numberFromString:weight.text];
With numberFromString:#"weight.text" you will be getting the value of the text 'weight.text' which is in fact 0.
But why not just double weightDouble = weight.text.doubleValue? (Except maybe localization concerns)

parsing string into different kind of number string

I have a string called realEstateWorth with a value of $12,000,000.
I need this same string to remain a string but for any number (such as the one above) to be displayed as $12 MILLION or $6 MILLION. The point is it needs the words "MILLION" to come after the number.
I know there is nsNumberFormatter that can convert strings into numbers and vice versa but can it do what I need?
If anyone has any ideas or suggestions, it would be much appreciated.
Thank you!
So as I see it, you have two problems:
You have a string representation of something that's actually a number
You (potentially) have a number that you want formatted as a string
So, problem #1:
To convert a string into a number, you use an NSNumberFormatter. You've got a pretty simple case:
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber *n = [f numberFromString:#"$12,000,000"];
// n is 12000000
That was easy! Now problem #2:
This is trickier, because you want a mixed spell-out style. You could consider using an NSNumberFormatter again, but it's not quite right:
[f setNumberStyle:NSNumberFormatterSpellOutStyle];
NSString *s = [f stringFromNumber:n];
// s is "twelve million"
So, we're closer. At this point, you could perhaps maybe do something like:
NSInteger numberOfMillions = [n integerValue] / 1000000;
if (numberOfMillions > 0) {
NSNumber *millions = [NSNumber numberWithInteger:numberOfMillions];
NSString *numberOfMillionsString = [f stringFromNumber:millions]; // "twelve"
[f setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *formattedMillions = [f stringFromNumber:millions]; // "$12.00"
if ([s hasPrefix:numberOfMillionsString]) {
// replace "twelve" with "$12.00"
s = [s stringByReplacingCharactersInRange:NSMakeRange(0, [numberOfMillionsString length]) withString:formattedMillions];
// if this all works, s should be "$12.00 million"
// you can use the -setMaximumFractionDigits: method on NSNumberFormatter to fiddle with the ".00" bit
}
}
However
I don't know how well this would work in anything other than english. CAVEAT IMPLEMENTOR
Worst case scenario, you could implement a category on NSString to implement the behaviour you want.
In the method that you would do in that category you could take an NSNumberFormatter to bring that string to a number and by doing some modulo operation you could define if you need the word Million, or Billion, etc. and put back a string with the modulo for Million or other way you need it to be.
That way you could just call that method on your NSString like this :
NSString *humanReadable = [realEstateWorth myCustomMethodFromMyCategory];
And also.
NSString are immutable, so you can't change it unless you assign a new one to your variable.
I'd recommend storing this value as an NSNumber or a float. Then you could have a method to generate an NSString to display it like:
- (NSString*)numberToCurrencyString:(float)num
{
NSString *postfix = #"";
if (num > 1000000000)
{
num = num / 1000000000;
postfix = #" Billion";
}
else if (num > 1000000)
{
num = num / 1000000;
postfix = #" Million";
}
NSString *currencyString = [NSString stringWithFormat:#"%.0f%#", num, postfix];
return currencyString;
}
Note: Your question states that your input needs to remain a string. That's fine. So you'd need to 1.) first parse the number out of the string and 2.) then reconvert it to a string from a number. I've shown how to do step 2 of this process.

How to format this NSString correctly?

I want to format a string that can look like that:
0.0580 which means 5.8 ct
0.1580 which means 15.8 ct
1.1580 which means 1.15 €
So the string can be anything in x.xxxx format. Now I started formating it but I am new to objective-c and iOS.
First I want to remove the last character because the last number does not really matter and I don't want to round numbers.
NSString *responseString = [responseData
substringWithRange:NSMakeRange(1,
[responseData length]-2)];
This gives me x.xxx so far. Any idea how to proceed and what code to use? Are there any libraries on that?
Take a look at the NSNumberFormatter class. It should do what you need. Something like this:
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
NSNumber *myNumber = [NSNumber numberWithDouble:[#"0.158" doubleValue]];
[numFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *formattedValue = [numFormatter stringFromNumber:myNumber];
[numFormatter release];
Also look at NSNumberFormatterStyle and NSNumberFormatterBehavior to control the format.
Once you have your number in the form x.xxx, you could do something like:
float floatValue = [#"0.158" floatValue]; // Get your string as a number.
floatValue *= 100; // Turn '0.158' into '1.58'
Does this answer your question? I'm not quite sure that it does, so update your question and I will try to assist you better.