Convert Double to NSString for label text - ios

I'm trying to get an NSNumber out of an NSMutableArray that's been previously manipluated as a double and then added to the array to print out in a label (NSString).
It's important that the number stays as an accurate representatoin of a double with no scientific notation to abbreviate the answer.
The other requirement is to have it print to maybe 15 or 16 decimal places, rounding is optional but not required.
I also do not want trailing 0's when displaying the double
I've tried the following but these do not work...
This is ok but ends the number with a . (eg: 1+1=2.)
double test = [[data.argOperands objectAtIndex:0]doubleValue];
label.text = [NSString stringWithFormat:#"%3.2f", test];
label.text = [label.text stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:#"0"]]];
I then try something like this, which is wrong because if I do 9^99 it'll print inf or 0.0003/4 it'll give scientific numbers instead of the value
float y = [[calcData.argOperands objectAtIndex:0]doubleValue];;
label.text = [NSString stringWithFormat:#"%g", y];
If I do the following using double it's getting close, 9^99 works, but 3.33/5 returns 0.666000 with trailing 0's
double y = [[data.argOperands objectAtIndex:0]doubleValue];
label.text = [NSString stringWithFormat:#"%f", y];
Any code examples of how to do it this way using either NSNumberFormatter or NSDecimalNumber would be greatly appreciated.

"%.13f" Would give you 13 decimal places, but that would give you trailing zeros.
You may need to create an NSNumberFormatter and use that.
I suspect you're not going to be happy no matter what. Binary floating point is not an exact representation of decimal. The decimal value .1 is not an exact value in binary, and might display as something like .09999999998 if you display it with 13 decimal places.
You also might look at using NSDecimalNumber, which stores values as decimal digits. It's slower than other ways of doing math but you can control the results exactly.

After looking over http://nshipster.com/nsformatter/ and the giant NSNumberFormatter_Class doc I've come up with this code that prints everything to my requirements:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setUsesSignificantDigits: YES];
numberFormatter.maximumSignificantDigits = 100;
[numberFormatter setGroupingSeparator:#""];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
label.text = [numberFormatter stringFromNumber:stringFromNumber:#(1234.567800000555)];
This will actually print 1234.56780000056 (missing the 12th decimal place and rounding it up to the 11th decimal place) though I'm happy enough with this.
I'm still cleaning up the answer, I don't need maximumSignificantDigits = 100 obviously, but generally having a large number there helps to ensure I'm getting all the decimal places I need.
I had to set setGroupingSeparator:#"" because NSNumberFormatterDecimalStyle puts commas in numbers and I don't want them (eg: Instead of getting 1,000 I want 1000).

Related

Inconsistent values with NSNumber to double multiplication

I'm currently parsing NSString values to NSNumbers and then adding them into a NSMutableArray called operands in an object called "data" like so:
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:*operandString];
[data.operands addObject:myNumber];
I then retrieve those numbers, perform some math on them, then update the array:
double x = [[data.operands objectAtIndex: i]doubleValue];
double y = [[data.operands objectAtIndex: i + 1]doubleValue];
double answer = x * y;
[data.operands replaceObjectAtIndex:(i) withObject:[NSNumber numberWithDouble:answer]];
When I get the answer, everything looks fine eg: ( 3.33 * 5 = 16.65)
BUT, when I look in the debugger I'm seeing some crazy values for x and answer, such as:
x = 3.3300000000000001
answer = 16.649999999999999
Why is this happening? Am I loosing some precision with parsing these back and fourth? Is it how I've used the NSNumberFormatter to parse the string?
The reason I'm in trouble with this is because I'm trying to ensure there's no double overflow errors so I'm using this simple test to check the integrity:
if (answer / y != x){
//THROW OVERFLOW ERROR
}
With the above crazy numbers this is always inconsistent. When I NSLog the answer it comes out fine:
NSLog (#"%g", [[data.operands objectAtIndex:i]doubleValue]]);
Same for
NSLog (#"%f", [[data.operands objectAtIndex:i]doubleValue]]);
You are not losing any precision that you need to worry about. Those are the correct values. There are only about 2^60 different double numbers, that finite set has to try to approximately cover the infinite 'number of numbers' in the range that doubles cover.
In other words, there are no exact answers in computer land and your
if (answer / y != x){
//THROW OVERFLOW ERROR
}
Will not work. Or it may work much of the time, but fail if you push it. Instead you need to acknowledge the limited precision (which is pretty high precision) of doubles:
//Don't waste time worrying like this...
if (fabs(answer / y - x) > 1e-12*fabs(answer)){
//Not correct or useful thing to check don't use this - i did not check
}
// let the math package handle it:
if (isnan(answer)){
// we gots problems
}
if (!isnormal(answer)){
// we gots some other problems
}
Also don't forget that 10^300 is a very large number, doubles work pretty well. To use 32 bit floats you need to pay much more attention to order of execution, etc.
NSLog is likely outputting with fewer decimals of precision, and rounds to the nearest thing, so the answers look better.

Adding Commas to Float or String?

I have been trying to find a way to find a way to append commas to a string or float. I have a float which could be anything from 10.50 to 50000000000.99 and would love to be able to format this to add commas to every 3 digits (not including the floats). I know that there is a NSNumberFormatter that can use NSNumberFormatterDecimalStyle or NSNumberFormatterCurrencyStyle but neither of those work with strings/floats. I have tried to split the float into two strings and then try to do a % of length == 3 calculation but it began to get really really messy. I did something similar in Java but it seems to be a lot harder in iOS.
If anyone have any suggestions or ideas? Any information or guidance is appreciated! Thanks in advance.
Edit: I know there are posts out there but none of them seem to solve the problem with doubles/floats/strings that end in zeros. For example, if I have a double as 16.00, the formatter will format that into 16. Same thing goes for a 1234.80. The formatter will format it into 1,234.8 instead of 1,234.80 and that is what I am looking for.
View this post on NSNumberFormatting here
The gist of it is to covert the float or double to a NSNumber and then use the NSNumberFormatter on the NSNumber to get a NSString with the desired format. Something like:
double doubleNum = 1000.002;
// Change double to nsnumber:
NSNumber *num = [NSNumber numberWithDouble:doubleNum];
// Set up the formatter:
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setUsesGroupingSeporator:YES];
[numFormatter setGroupingSeparator:#","];
[numFormatter setGroupingSize:3];
// Get the formatted string:
NSString *stringNum = [numFormatter stringFromNumber:num];
NSLog(#"%#",stringNum);
// prints out '1,000.002'
Give it a try, there are lots of different formatting settings you can apply.
Read Apple's guide to formatting numbers, NSNumberFormatter supports both thousand separators and fractional parts. For example see Listing 1 in the referenced doc.

Decimal pad can't do math with comma. Need dot

I have app with three view controllers. First is UIViewController with three UITextField's where user put some digits. These digits are stored to my CoreData entity as String attributes.
Second is UITableView, where I show my stored data from CoreData as new cell.
Third is detail UIViewController where I show user all his previously inserted digits.
The problem is when I set on textField decimal pad, user have digits and comma but my function need digits with dot for double precision calculating.
With comma I can't make mathematical function as [.....] * [...] = .... because it doesn't work.
Any idea how I can figure it out?
Can I simply change that comma to a dot?
I have this code:
NSNumberFormatter*nf = [[NSNumberFormatter alloc]init];
[nf setNumberStyle:NSNumberFormatterDecimalStyle];
double result = [myString doubleValue] * [myOtherString doubleValue];
You want the decimal keypad to have either a comma or a period (dot) based on the user's locale. This is so the user can enter the value as they are accustomed to. In order for you to do the math with the vales, you need to use a NSNumberFormatter to convert the entered string into a double value. Once you do this, your math formulas will work. Never use doubleValue or floatValue to convert an NSString to a double or float if the string was entered by the user. Always use NSNumberFormatter to properly deal with the user's locale.
Update based on code added to question.
You don't use the number formatter. You are doing exactly what I said not to do. Change your code to:
double firstValue = [[nf numberFromString:myString] doubleValue];
double secondValue = [[nf numberFromString:myOtherString] doubleValue];
double result = firstValue * secondValue;
Solution is very simple:
1. Go to Settings > General > International > Regional Format
2. Now select "United States"
Now run your App and see dot(.) instead of comma(,) in Decimal pad keyboard.

How to get format numbers with decimals (XCode)

My objective is to create a customer calculator application for iPhone and I am using Xcode to write my application. My problem, that I cannot find a solution for, is how to format a number that uses decimals (with extra zeros) without switching into scientific notation
I tried...
buttonScreen.text = [NSString stringWithFormat:#"%0.f",currentNumber];
%0.f formatting always rounds so if the user types in "4.23" it displays "4"
%f formats numbers with 6 decimals (typing in '5' displays as '5.000000'), but I don't want to show extra zeros on the end of the number.
%10.4f is something else that I have seen in my reading to find the solution, but my problem is that I don't know how many decimals will be in the answer, and I may want zero decimals or 10 decimals depending on the number.
The following are examples of numbers I'd like to display (without the commas): A whole number larger than 6 digits, a decimal number with more than 6 digits.
123,456,789;
0.123456789;
12345.6789;
-123,456,789;
-0.23456789;
-12345.6789;
*This is a spiritual repost to my earlier question "How to Format Numbers without scientific notation or decimals" which I poorly phrased as I intended to write 'unnecessary (extra zeros),' but upon rereading my post clearly witnessed my inability to convey that at any point in my question.
Use the NSNumberFormatter class.
First define the formatter:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
Then you can define various properties of the formatter:
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.maximumIntigerDigits = 3;
formatter.minimumFractionDigits = 3;
formatter.maximumFractionDigits = 8;
formatter.usesSignificantDigits = NO;
formatter.usesGroupingSeparator = YES;
formatter.groupingSeparator = #",";
formatter.decimalSeparator = #".";
....
You format the number into a string like this:
NSString *formattedNumber = [formatter stringFromNumber:num];
Play around with it. Its pretty simple, but may take some work to get the look you would like.
Actually, it makes more sense to use this:
label.text = [NSString stringWithFormat:#"%.4f", answer];
This tells XCode to display your number with 4 decimal places, but it doesn't try to "pad" the front of the number with spaces. For example:
1.23 -> " 1.2300" // When using [NSString stringWithFormat:#"%9.4f", answer];
1.23 -> "1.2300" // When using [NSString stringWithFormat:#"%.4f", answer];
try something like this
label.text = [NSString stringWithFormat:#"%9.4f", answer];
where the 9 means total digits (in terms of padding for alignment), and the 4 means 4 decimal places.

drop decimals in this method

I have a statement that shows 50.02%
How can I drop the decimals and show 50%?
Sorry this is so basic, pretty new to xcode.
Thank you in advance.
-(void)updatePercent{
percent.text = [NSString stringWithFormat:#"%.2f%#", 100.0f, #"%"];
}
Use this:
percent.text = [NSString stringWithFormat:#"%.0f%%", 100.0f];
Also note the use of %% to print a single %.
When printing floats, you can control how many decimals places are printed out by using numbers between the % and the f in the %f format statement.
The number on the right of the decimal tells how many decimal places should be printed. The number on the left of the decimal tells at least how many total places should be printed (including the decimal and all digits). If the number on the left is prefixed by a zero, the resulting string will have zeros appended to the left.
float myNum = 32.142;
// without declaring total digits
[NSString stringWithFormat:#"%.0f"] // 32
[NSString stringWithFormat:#"%.2f"] // 32.14
[NSString stringWithFormat:#"%.5f"] // 32.14200
// put a zero in front of the left digit
[NSString stringWithFormat:#"%010.0f"] // 0000000032
[NSString stringWithFormat:#"%010.2%"] // 0000032.14
// without the zero prefix (leading whitespace)
[NSString stringWithFormat:#"%10.2f"] // 32.14

Resources