How do I create a number formatter for formatting large numbers with commas?
For example, 2389378.289 should become 2,389,378.289
Note that there is not always three decimal places, nor is there always a decimal at all. Please use NSNumberFormatter.
Thanks!
NSNumberFormatter *fmt = [[[NSNumberFormatter alloc] init] autorelease];
[fmt setAlwaysShowsDecimalSeparator:NO];
[fmt setFormat:#"#,##0.###"];
NSLog(#"%#",[fmt stringFromNumber:[NSNumber numberWithFloat:35.424252]]);
NSLog(#"%#",[fmt stringFromNumber:[NSNumber numberWithFloat:21.3]]);
NSLog(#"%#",[fmt stringFromNumber:[NSNumber numberWithFloat:10392425]]);
The format Chuck gave you supports up to 3 decimal places. If you have a number with less than 3 they just don't show up. Chuck is also correct that you want to take a look at the Unicode number format guide, it is invaluable for number formatting issues.
The format for that would be #"#,##0.###". Take a look at the Unicode number format guide for a full explanation of how to construct format strings.
(Also note that this works correctly in locales where commas and dots are reversed, or where other characters are used.)
Related
I know the way to set formatted float with specific number
NSLog(#"%.2f", myFloat);
What is the way to set parameter number? Something like this
cell.lblOpenPrice.text = [NSString stringWithFormat:#"%.%if", trade.open_price, trade.digits];
You should use an instance of NSNumberFormatter for this. There are dozens of options, too many to discuss them here. I. e. you can set the total number of digits (significant digits) or the number of integer and fraction digits as discussed here.
NSNumberFormatter *formatter = [NSNumberFormatter new];
// Do the desired configuration
NSString *text = [formatter stringFromNumber:#(myFloat)];
To set a field precision dynamically you use an asterisk in the format and provide the precision argument first, so your code example is:
cell.lblOpenPrice.text = [NSString stringWithFormat:#"%.*f", trade.digits, trade.open_price];
HTH
I have some string s that is locale specific (eg, 0.01 or 0,01). I want to convert this string to a NSDecimalNumber. From the examples I've seen thus far on the interwebs, this is accomplished by using an NSNumberFormatter a la:
NSString *s = #"0.07";
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[formatter setGeneratesDecimalNumbers:YES];
NSDecimalNumber *decimalNumber = [formatter numberFromString:s];
NSLog([decimalNumber stringValue]); // prints 0.07000000000000001
I'm using 10.4 mode (in addition to being recommended per the documentation, it is also the only mode available on the iPhone) but indicating to the formatter that I want to generate decimal numbers. Note that I've simplified my example (I'm actually dealing with currency strings). However, I'm obviously doing something wrong for it to return a value that illustrates the imprecision of floating point numbers.
What is the correct method to convert a locale specific number string to an NSDecimalNumber?
Edit: Note that my example is for simplicity. The question I'm asking also should relate to when you need to take a locale specific currency string and convert it to an NSDecimalNumber. Additionally, this can be expanded to a locale specific percentage string and convert it to a NSDecimalNumber.
Years later:
+(NSDecimalNumber *)decimalNumberWithString:(NSString *)numericString in NSDecimalNumber.
Based on Boaz Stuller's answer, I logged a bug to Apple for this issue. Until that is resolved, here are the workarounds I've decided upon as being the best approach to take. These workarounds simply rely upon rounding the decimal number to the appropriate precision, which is a simple approach that can supplement your existing code (rather than switching from formatters to scanners).
General Numbers
Essentially, I'm just rounding the number based on rules that make sense for my situation. So, YMMV depending on the precision you support.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[formatter setGeneratesDecimalNumbers:TRUE];
NSString *s = #"0.07";
// Create your desired rounding behavior that is appropriate for your situation
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
NSDecimalNumber *decimalNumber = [formatter numberFromString:s];
NSDecimalNumber *roundedDecimalNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
NSLog([decimalNumber stringValue]); // prints 0.07000000000000001
NSLog([roundedDecimalNumber stringValue]); // prints 0.07
Currencies
Handling currencies (which is the actual problem I'm trying to solve) is just a slight variation on handling general numbers. The key is that the scale of the rounding behavior is determined by the maximum fractional digits used by the locale's currency.
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[currencyFormatter setGeneratesDecimalNumbers:TRUE];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// Here is the key: use the maximum fractional digits of the currency as the scale
int currencyScale = [currencyFormatter maximumFractionDigits];
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:currencyScale raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
// image s is some locale specific currency string (eg, $0.07 or €0.07)
NSDecimalNumber *decimalNumber = (NSDecimalNumber*)[currencyFormatter numberFromString:s];
NSDecimalNumber *roundedDecimalNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
NSLog([decimalNumber stringValue]); // prints 0.07000000000000001
NSLog([roundedDecimalNumber stringValue]); // prints 0.07
This seems to work:
NSString *s = #"0.07";
NSScanner* scanner = [NSScanner localizedScannerWithString:s];
NSDecimal decimal;
[scanner scanDecimal:&decimal];
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithDecimal:decimal];
NSLog([decimalNumber stringValue]); // prints 0.07
Also, file a bug on this. That's definitely not the correct behavior you're seeing there.
Edit: Until Apple fixes this (and then every potential user updates to the fixed OSX version), you're probably going to have to roll your own parser using NSScanner or accept 'only' double accuracy for entered numbers. Unless you're planning to have the Pentagon budget in this app, I'd suggest the latter. Realistically, doubles are accurate to 14 decimal places, so at anything less than a trillion dollars, they'll be less than a penny off. I had to write my own date parsing routines based on NSDateFormatter for a project and I spent literally a month handling all the funny edge cases, (like how only Sweden has the day of week included in its long date).
See also Best way to store currency values in C++
The best way to handle currency is to use an integer value for the smallest unit of the currency, i.e. cents for dollars/euros, etc. You'll avoid any floating point related precision errors in your code.
With that in mind, the best way to parse strings containing a currency value is to do it manually (with a configurable decimal point character). Split the string at the decimal point, and parse both the first and second part as integer values. Then use construct your combined value from those.
This question already has answers here:
Easiest way to format a number with thousand separators to an NSString according to the Locale
(5 answers)
Closed 8 years ago.
I'm looking for a way to format a string into number and show it on textfield
For example: I have the number "1000", I want to it convert into "1.000" or 100000 into 100.000. Or 1000000 into 1.000.000. Please help me if you know solution for this
Thanks
If you want to format a number as currency, then you need to use NSNumberFormatter. However, the other answers are wrong because they tell you to use the wrong numberStyle or tell you to change the format string. These are both incorrect.
First, you want an NSNumberFormatter:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
Next, you need to tell it you're going to be formatting things for currency:
formatter.numberStyle = NSNumberFormatterCurrencyStyle;
Optionally, if you want things to be formatted in a specific currency, you may set the currency code:
formatter.currencyCode = #"USD";
Optionally, if you want things to be formatted according to the locale settings that are not the user's default locale, you may set the locale:
formatter.locale = [NSLocale localeWithLocaleIdentifier:#"en_GB"];
If you were to run those four lines of code, you would get an NSNumberFormatter that formats an NSNumber in US Dollars, but according to the Great Britain locale. The locale is what defines the placement of the currency symbol (before or after the number), the decimal separator (. vs ,), the thousands separator (, vs ), and so on.
The currency code defines what the currency symbol is ($ vs £, etc).
By default, the locale is [NSLocale currentLocale], and the currency code is the code for the current locale.
One very very very important thing to remember, however, is that this only formats currency for you. It does not perform any currency conversion for you. It assumes that whatever NSNumber you give it is already in units of the target currency.
You can use the NSNumberFormatter class as follows.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSLog(#"%#", [formatter stringForObjectValue:#2333999878]);
This class is very powerful and will also allow you to localize the currency beside the formatting
You can do like this:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setPositiveFormat:#"#.###"];
NSString *string = [numberFormatter stringFromNumber:[NSNumber numberWithInt:1000]];
I'm having a serious dispute with NSNumberFormatter, and even after going through its extensive documentation, I haven't quite been able to wrap my head around a pretty straightforward issue that I encountered. I hope you guys can help me out.
What I have: an NSDecimalNumber representing a calculation result, displayed in a UITextField
What I need: Scientific notation of that result.
What I'm doing:
-(void)setScientificNotationForTextField:(UITextField*)tf Text:(NSString*)text {
NSString* textBefore = text;
// use scientific notation, i.e. NSNumberFormatterScientificStyle
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
//[formatter setGeneratesDecimalNumbers:YES];
[formatter setNumberStyle:NSNumberFormatterScientificStyle];
NSDecimalNumber* number = (NSDecimalNumber*)[formatter numberFromString:text];
tf.text = [number descriptionWithLocale:[[Utilities sharedUtilities] USLocale]];
NSString* textAfter = tf.text;
// DEBUG
NSLog(#"setScientificNotation | text before = %#, text after = %#", textBefore, textAfter);
[formatter release];
}
What happens:
A certain result may be 0.0099. textBefore will hold that correct value. If I don't tell the formatter to generate decimal numbers (commented out in the above snippet), it will create an NSNumber from an NSDecimalNumber which creates a false result and turns textAfterinto 0.009900000000000001 - a rounding error due to the reduced precision of NSNumber over NSDecimalNumber.
If I do tell the NumberFormatter to generate decimals, it will still create the wrong result . And what's more, where before it would insert the exponent notation (e.g. "1.23456e-10"), it would now generate (and thus display) the full decimal number, which is not what I want.
Again, I'd like to have the formatter use NSDecimalNumber so it doesn't falsify results plus have exponent notation where necessary.
Am I using the class wrong? Did I misinterpret the documentation? Can someone explain why this happens and how I can create the behavior I want? I will of course continue researching and update if I find anything.
You can't just cast an NSNumber to an NSDecimalNumber and expect it to work. If your number is not too complex, you can ditch NSNumberFormatter and try using this instead:
NSDecimalNumber* number = [NSDecimalNumber decimalNumberWithString:text];
That will give you an actual NSDecimalNumber instance, with its precision.
Unfortunately, setGeneratesDecimalNumbers: doesn't work properly. It's a known bug.
If your number is too complex to work with decimalNumberWithString:, you're probably out of luck with Apple's APIs. Your only options are either parsing the string manually into something NSDecimalNumber can understand or performing some post-processing on the imprecise value given to you by NSNumberFormatter.
Finally, if you really want a number in scientific notation, why not just use the number formatter you just used? Just call stringFromNumber: to get the formatted value.
I have a class holding various types of numeric values. Within this class I have a couple of helper methods that are used to output descriptor text for display within my application.
This descriptor text should always appear as an integer or float, depending on the definition of the particular instance.
The class has a property, DecimalWidth, that I use to determine how many decimals to display. I need help writing a line of code that displays the numeric value, but with a fixed number of decimals, (0 is a possibility, and in such a case the value should be displayed as an integer.)
I am aware that I can could return a value like [NSString stringWithFormat:#"%.02f", self.Value] but my problem is that I need to replace the '2' in the format string with the value of DecimalWidth.
I can think of couple ways of solving this problem. I could concat a string together and that is as the format string for the outputted string line. Or, I could make a format string within a format string.
These solutions sound hideous and seem rather inefficient, but maybe these are the best options that I have.
Is there an elegant way of constructing a dynamic formatting string where the output is a fixed decimal width number but the specified decimal width is dynamic?
That doesn't sound hideous or inefficient to me.
[NSString stringWithFormat:[NSString stringWithFormat:#"%%.%df", DecimalWidth], self.Value]
In fact I think it is rather elegant.
However one solution for the problem is definitely question suggested by #lulius caesar,
But one good way is also using NSNumberFormatter. Below is a sample code you can use to generate decimal values with fixed decimal number
NSNumberFormatter *numberFormatter=[[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMinimumFractionDigits:DecimalWidth];
[numberFormatter setMaximumFractionDigits:DecimalWidth];
NSString * decimalString = [numberFormatter stringFromNumber:[NSNumber numberWithFloat:self.value]]]