NSDecimalNumber round long numbers - numbers

I'm trying to get NSDecimalNumber to print out large numbers, 15 or more digits. At 15 digits I see 111,111,111,111,111. Above 15 digits I see 1,111,111,111,111,110 even though the number being formatted is 1111111111111111.
An example to illustrate my problem:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumSignificantDigits:25];
[formatter setUsesSignificantDigits:true];
NSDecimalNumber* test = [NSDecimalNumber decimalNumberWithString:#"12345678901234567890"];
NSString* output = [formatter stringFromNumber:test];
NSLog( #"num value: %#", test );
NSLog( #"str value: %#", output );
And the output looks like:
2010-09-16 09:24:16.783 SimpleCalc[739:207] num value: 12345678901234567890
2010-09-16 09:24:16.784 SimpleCalc[739:207] str value: 12,345,678,901,234,600,000
What silly thing have I missed?

The problem here is that NSNumberFormatter does not handle NSDecimalNumbers internally, they are converted to double and you are seeing the resulting loss in precision. From the docs:
The representation encompasses integers, floats, and doubles; floats and doubles can be formatted to a specified decimal position.
You should probably be taking a look at the - (NSString *)descriptionWithLocale:(NSDictionary *)locale method on NSDecimalNumber.

Or NSDecimalString(). Take your NSDecimalNumber (e.g. myDecimalNumber), extract the NSDecimal via decimalValue (NSDecimal decimal = [myDecimalNumber decimalValue]) and create an NSString with the NSString *myString = NSDecimalString(decimal) function.
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/index.html#//apple_ref/c/func/NSDecimalString

Related

NSNumberFormatter's multiplier rounds down instead of showing fraction

I have configured an NSNumberFormatter to convert amounts that are stored as cents in an NSDictionary to euro's. Because they're stored as cents, I have set the formatter's multiplier to [NSNumber numberWithDouble:0.01]. However, when I try to display 304 euro cents as euro's I get € 3,00.
This leads me to believe that the multiplier is doing integer division instead of double division.
NSFormatter configuration
/**
Returns an NSNumberFormatter that can be used to display currency in euro's (as determined in The Netherlands).
*/
+ (NSNumberFormatter *)euroCurrencyFormatter
{
static NSNumberFormatter *numberFormatter = nil;
#synchronized(self) {
if (!numberFormatter) {
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setMultiplier:[NSNumber numberWithDouble:0.01]];
NSLocale *nlLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"nl_NL"];
[numberFormatter setLocale:nlLocale];
[nlLocale release];
}
}
return numberFormatter;
}
Calling the NSFormatter
cell.detailTextLabel.text = [[NSNumberFormatter euroCurrencyFormatter] stringFromNumber:[breakdown valueForKey:#"VatAmount"]]; // The VAT amount would be 304.
Result
€ 3,00
How can I stop errounous behaviour?
Try this code.
cell.detailTextLabel.text = [[NSNumberFormatter euroCurrencyFormatter] stringFromNumber:[NSNumber numberWithDouble:[[breakdown valueForKey:#"VatAmount"] doubleValue]]]; // The VAT amount would be 304.
As if you pass VAT as a integer you will get the number always in int format.
See the "Configuring Rounding Behavior" of the NSNumberFormatter reference.

Formatting float values

This is probably a stupid question but anyway.
I wan the number I set on my label to be formated nicely like this 20,000,000 .
How do I do this ?
For now I've set the number of decimal points to 0 so I just get the whole number without any places.
[NSString stringWithFormat:#"%.0f", slider.value];
you can use the following formatter:
-(void)setCurrencyFormat
{
NSNumberFormatter *CurrencyFormat = [[NSNumberFormatter alloc] init];
[CurrencyFormat setNumberStyle:NSNumberFormatterCurrencyStyle];
label.text= [CurrencyFormat stringFromNumber:[NSNumber numberWithDouble:billAmountInDouble]];
NSString *st1=[NSString stringWithFormat:#"%#",[CurrencyFormat stringFromNumber:[NSNumber numberWithDouble:individualTaxInDouble]]];
label.text=st1;
}
Check out the docs for NSNumberFormatter - you can do pretty much everything with that.

How to set string in currency format to normal number format?

How to set string in currency format to normal number format in iphone? i have a number in currency format say "Rs 10,000" or "$ 1000,000".now i am saving this in my database as a string in normal number format like "10000" or "1000000" ..so how to convert it to this form.. because only with the latter string i can use [string intValue] for use in calculations
Are you using a NSNumberFormatter to set the currency style according to the locale? If so just extract it as a NSNumber object:
NSDecimalNumber *currencyAmount = [NSDecimalNumber decimalNumberWithString:#"100.00"];
NSNumberFormatter *currency = [[NSNumberFormatter alloc] init];
[currency setNumberStyle:NSNumberFormatterCurrencyStyle];
[currency setLocale:yourLocale];
NSString *yourstring = [NSString stringWithFormat:#"%#", [currency stringFromNumber:someAmount];
NSNumber* number = [currency numberFromString:yourString];

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.

Custom floating decimal points

label.text = [NSString stringWithFormat:#"%.2f",final];
The above statement displays the float value available in the variable "final" with two digits after decimal point.
I want to display number of decimals in depending upon the number i have give to a integer variable like this
label.text = [NSString stringWithFormat:#"%.if",j,final]
Here j is integer variable. Whatever the number i have taken for j that many decimals it should display. I need proper syntax to display the above statement.
The IEEE printf spec that Apple follows states:
A field width, or precision, or both, may be indicated by an asterisk
( '*' ). In this case an argument of type int supplies the field width
or precision.
This means that
label.text = [NSString stringWithFormat:#"%.*f",j,final]
might work, but I have no platform available to test it right now.
NSNumberFormatter has the ability to do what you want. Any of the following methods can be set using a variable before you format your string.
- (void)setMinimumIntegerDigits:(NSUInteger)number
- (void)setMinimumFractionDigits:(NSUInteger)number
- (void)setMaximumIntegerDigits:(NSUInteger)number
- (void)setMaximumFractionDigits:(NSUInteger)number
Data Formatting Guide - Number Formatters
I don't know if there's a one-liner that will do what you want, but you can always do:
NSString* formatString = [NSString stringWithFormat: #"%%.%if", j];
label.text = [NSString stringWithFormat:formatString, final];
You can use NSNumberFormatter,
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setFormatterBehavior:NSNumberFormatterBehaviorDefault];
[nf setNumberStyle:NSNumberFormatterDecimalStyle];
[nf setMaximumFractionDigits:j]; // Set the number of decimal places here
label.text = [nf stringFromNumber:[NSNumber numberWithFloat:final]];
[nf release];