Precision error using NSNumberFormatter numberFromString - objective-c

Why does the following code produce "numberFromString = 9.390000000000001" rather than "numberFromString = 9.39"?
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numFormatter setPositiveFormat:#"$##0.00"];
[numFormatter setNegativeFormat:#"-$##0.00"];
NSNumber *nTCA = [numFormatter numberFromString:#"$9.39"];
NSLog(#"numberFromString = %#", nTCA);
I get the above results on OS X 10.6 and iOS 4.3.3.
What's the best way to correct this error?
Thanks

I suspect you are running into an error as a result of using floating-point precision. The way to fix this is to use NSDecimalNumber instead of NSNumber. There's a great post about this here.
NSDecimalNumber has a + decimalNumberWithString: method. Would that suffice for your purposes?

Related

How to properly display currency iPhone/Objective-C

I am trying to properly display properly formatted currencies from long values. I am using NSNumberFormatter however it seems to be cutting off my decimal places where the cents would go.
For example, if I have a long value of 1203 (cents) I want it to have a fixed point format (like 12.03). Here is what I have done:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterCurrencyStyle;
formatter.currencyCode = "USD";
formatter.multiplier = [NSNumber numberWithDouble:0.01];
long currencyAmount = 1203;
NSNumber *number = [NSNumber numberWithLongLong:currencyAmount];
[label setText:[formatter stringFromNumber:number]];
I am getting this output $12.00 but I want $12.03
To think of an integer cut-off bug inside of NSNumberFormatter is crazy speculation but have you tried the default multiplier of one and dividing your currency amount after conversion to float by 100 yourself?
EDIT: For this workaround the following post suggests the use of NSDecimalNumber to avoid rounding problems. NSNumberFormatter to format currency not working for floats
I figured out the answer. This will properly format a long/long long value to a currency.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterCurrencyStyle;
formatter.currencyCode = "USD";
long currencyAmount = 1203;
NSDecimalNumber *wrappedCurrencyAmount = [NSDecimalNumber decimalNumberWithMantissa:currencyAmount exponent:-2 isNegative:NO];
[label setText:[formatter stringFromNumber:wrappedCurrencyAmount]];

convert NSString TO NSNumber accurately with decimal

Lets say my string value is as follows
12345.12
after converting it to NSNumber its coming as 12345.1223122
But I want the accurate number from string
Is there a way to achieve it.
Code that I'm using right now
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber * myNumber = [f numberFromString:aString];
[f release];
If you're dealing with currency-type numbers (just a guess from your use of the currency style formatter) you probably want to use NSDecimalNumber. Unlike standard floating point types, decimal numbers use a base-10 exponent so that you always get exactly the expected accuracy when dealing with money problems — i.e. they're the same as using integers and then moving the decimal point around in the base-10 representation.
Try Like this...
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber * myNumber=[NSNumber numberWithFloat:[[f numberFromString:aString] floatValue]];
I think it will be helpful to you.
Do this:
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
[f setMaximumFractionDigits:2];
NSNumber * myNumber = [f numberFromString:aString];
[f release];
NSLog(#"%#",myNumber);
It's a few years, but this works:
double d = [#"123.45" doubleValue];
NSNumber* n = [NSNumber numberWithDouble:d];

Getting nil from NSNumberformater numberFromString

I'm trying to format an amount from a .txt file coming in es_US locale(x,xxx.xx), to my current locale with is es_ES(x.xxx,xx). I would expect that [NSNumberFormater numberFromString] would just reformat the string, however and I'm only getting a nil value from this method.
I also tried another approach after checking the answers from here, but NSDecimalnumber does not work if the string has thousand separators, so if anybody could tell me what am I doing wrong please...
- (void) setSaldo_sap:(NSString *)saldo_sap
{
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setLocale:[NSLocale currentLocale]];
[numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numFormatter setNegativeFormat:#"-¤#,##0.00"];
//saldo_sap = #" -324,234.55"
NSString * tmpString = [saldo_sap stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSNumber *num = [numFormatter numberFromString:tmpString];
NSDecimalNumber *tempNumber = [NSDecimalNumber decimalNumberWithString:tmpString];
_saldo_sap = [numFormatter stringFromNumber:tempNumber];
}
I think you misinterpret the aim of NSNumberFormatter: it doesn't "reformat", it "formats" and "parses" a numbers formatted along the set rules. So if you have numbers coming in "es_US" locale but want to format them using "es_ES" you will need two NSNumberFormatters: one for each locale.
Parse the incoming number with "es_US" and format using "es_ES", simplifying a bit (I don't know those two locales and the exact format of your numbers so you may need to tweek it a bit):
NSString * tmpString = ...
NSNumberFormatter *usFormatter = [[NSNumberFormatter alloc] init];
[usFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier: #"es_US"] autorelease]];
[usFormatter setHasThousandSeparators: YES];
NSNumberFormatter *esFormatter = [[NSNumberFormatter alloc] init];
[esFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier: #"es_ES"] autorelease]];
[esFormatter setHasThousandSeparators: YES];
// this assignment looks also somewhat weird: is it an instance variable?
// 'cause if it is and you assign an autoreleased string you'll have a bad pointer there
_saldo_sap = [esFormatter stringFromNumber: [usFormatter numberFromString: tmpString]];
// And unless you use ARC you leak your formatter on each call, so at the end
[usFormatter release];
[esFormatter release];
EDIT
If the input strings contain prefix/postfix characters, that may prevent NSNumberFormatter to work (it use usually pretty strict), use setLenient::
"Sets whether the receiver will use heuristics to guess at the number which is intended by a string."
If you have more than one number to be converted, do not create the formatters for each number, this is just a waste of memory and cpu. Make them instance variables and reuse. It will be much clearer than just having one formatter and reconfiguring it between parsing one format and formatting in another.
NSString *_saldo_sap = #" -324234.55";
//NSString *_saldo_sap = #" 324,234.55";
NSString * tmpString = [_saldo_sap stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//tmpString = #"-324,234.55"
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
NSNumber *num = [numFormatter numberFromString:tmpString];
[numFormatter setLocale:[NSLocale currentLocale]];
[numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numFormatter setNegativeFormat:#"-¤#,##0.00"];
_saldo_sap = [numFormatter stringFromNumber:num];
Firstly, for getting NSNumber from NSString the string must be in correct readable format i.e. it must not include any characters like " , " as stated.
Secondly, you must first convert the string to NSNumber and then format it accordingly.

How to format and print float numbers on iOS?

I would like to create a formatted output of a floating point number with correct localization on Cocoa-Touch. The output should be equivalent to that of printf("%<a>.<b>f", n), where <a> is the total number of digits and <f> is the maximum number of fractional digits.
Setup of NSNumberFormatter with <a>=6 and <f>=2: (Platform is iOS 5.1 SDK, Xcode 4.3.3 and the iPhone Simulator 5.1)
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterDecimalStyle];
[nf setPaddingCharacter:#" "];
[nf setUsesGroupingSeparator:NO];
[nf setLocale:[NSLocale autoupdatingCurrentLocale]];
[nf setUsesSignificantDigits:YES];
[nf setMaximumSignificantDigits:6];
[nf setMaximumFractionDigits:2];
[nf setRoundingMode:NSNumberFormatterRoundFloor];
NSLog(#"Test: %#", [nf stringFromNumber:[NSNumber numberWithDouble:2.64324897]]);
Expected output (with German locale): Test: 2,64
Observed output (with German locale): Test: 2,64324
Other observations:
I have tried to use different values for the fraction digits, e.g. [nf setMaximumFractionDigits:4] or [nf setMaximumFractionDigits:0]. The result is unchanged, it appears that the fraction digits are ignored. Changing the locale to US only changes the , to a ., not the number of fraction digits.
Question: How can I translate the printf-format string correctly to an NSNumberFormatter?
Ryan is not totally wrong. Use the localizedStringWithFormat method:
using objective-c
NSNumber *yourNumber = [nf numberFromString:yourString];
//to create the formatted NSNumber object
NSString *yourString = [NSString localizedStringWithFormat:#"%.2F", yourNumber];
//to create the localized output
using SWIFT 3
let yourString: String
yourString = String.localizedStringWithFormat("%.2F", yourDoubleNumber) //no need for NSNumber Object
A little bit late but it still might help. Good luck!

Objective-C: How to format string as $ Price

Is their a built-in way of formatting string as $ price, e.g. 12345.45 converted to $12,345.45?
Assuming you are using Cocoa (or just Foundation), you can use NSNumberFormatter and set its style to currency:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
... = [formatter stringFromNumber:number];
By default it uses the locale of your system, but you can change that and lots of other properties, see the NSNumberFormatter API docs.
Assuming the price is held in a float, you probably want +localizedStringWithFormat:.
NSString *priceString = [NSString localizedStringWithFormat:#"$ %'.2f",price];
Hmmm... Apple says they follow the IEEE standard for printf, so it should accept the ' flag, but it doesn't work on Tiger. NSNumberFormatter it is.
You need to get rid of the ' character
So, just have this:
NSString *priceString = [NSString localizedStringWithFormat:#"$ %.2f", price];
NSString *formatedNumbers = [NSNumberFormatter localizedStringFromNumber:myNumber numberStyle:NSNumberFormatterCurrencyStyle];