How to round a float to 2 decimal places? - objective-c

This is my algorithm to find out the speed of my game.
self.speed=.7-self.score/50;
Now how can I make self.speed round to 2 decimal places?

Note: my answer assumes you only care about the number of decimals for the purpose of displaying the value to the user.
When you setup your NSNumberFormatter to format the number into a string for display, setup the formatter with a maximum of two decimal places.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2];
NSString *formattedNumber = [formatter stringFromNumber:#(self.speed)];
You have the option of using the setRoundingMode: method if you need a specific round method.
BTW - you shouldn't use a string format for this because it doesn't take the user's locale into account to format the number properly.

floats are handled in IEEE754 format, you can't directly decide how many decimal places will be used.You can directly decide how many bits will be used, or indirectly round the las part of the number doing this:
NSString* str=[NSString stringWithFormat: #"%.2f", number];
number= atof([str UTF8String]);
But like maddy pointed, you only need to round/truncate the unwanted decimal digits only when presenting the number to the user, so you could only use the %.2f format specifier when printing it, or use a formatter.

self.speed = (int)(self.speed * 100 + 0.5) / 100.0;
if you want to have that as a string:
NSString *speedString = [NSString stringWithFormat: #"%.2f", self.speed];

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.

Converting NSString to NSNumber results in too many digits and strange rounding

When converting an NSString, which contains standard decimal numbers with two digits (e.g. 8.20) to a NSNumber, I get (from time to time) extra digits and a strange rounding behavior when logging the result via NSLog or saving it in Core Data (as float or double), e.g. 8.20 -> 8.199999999999999.
This is the code I am using to convert the numbers:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:5];
NSNumber *num = [numberFormatter numberFromString:str];
I do not understand why the conversion to NSNumber messes the number up. What is wrong with my code?
This is just how float and double behaves in C/Objective-C (and many other languages). For example, when you type into python 8.0, the result would be 8.000000000001. I recommend using NSScanner to convert them into primitive number types (double, float).
Why would you use NSNumberFormatter to convert string to float, it would be an overkill,
To convert it just use
NSNumber *num = [NSNumber numberWithFloat:[str floatValue]];
I have encounter the problem when I use NSNumber to save the doublevalue
of 8.28 always show the 8.2799999999...,I guess it cause by a computer numerical precision
Try this code.
+ (NSString *)dealWithDouble:(double)doubleValue {
double d2 = doubleValue;
NSString *d2Str = [NSString stringWithFormat:#"%lf", d2];
NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:d2Str];
NSString *str2D = [num stringValue];
return str2D;
}
Don't use floatValue. floatValue only gives 24 bit of precision. doubleValue gives 53 bits of precision. If you use numbers over a million dollars for example, floatValue cannot give you any values that are closer than six cent apart. ($1,000,000 followed by $1,000,000.06 etc. )
The rule is: Don't use float unless you know a reason why you should use float and not double.

Rounding behavior when NSNumberFormatter reads string?

I have this sample code:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSString *numberString = #"9.2";
NSNumber *number = [formatter numberFromString:numberString];
NSLog(#"String: %#, Number: %#", numberString, number);
The printed result is:
String: 9.2, Number: 9.199999999999999
I don't understand why this would happen. Am I missing a setting?
According to this reference, an NSNumber can store any ordinary C numeric type. Since this is obtained by parsing a non-integer, the two types to choose from are float and double, and by the displayed value, the chosen representation is double.
Since decimal fractions like 9.2 aren't exactly representable as doubles, you get the closest representable number. That is displayed to default precision, which is about 16 decimal places.

Dynamicaly rounding numbers in Objective-C

I know that there are many different questions about this sort of topic on SO already, but I couldn't find a way to tailor them all to my specific needs.
What I have is a floating point number that gets sent to me through the network that I need to convert and graph out to the screen. The numbers can range from 5.2, 285.159, 294729172.258, -10734.112, etc. What I would like to do is get the value used to round from one digit below the most significant digit.
Example:
5.2 = 5
285.159 = 300
294729172.258 = 300000000
-10734.112 = -11000
Any advice that can be used to help guide me would be greatly appreciated.
Here's my solution:
int roundMostSignificant(float input)
{
NSNumber *number = [NSNumber numberWithFloat:input];
static NSNumberFormatter *formatter = nil;
if (!formatter)
{
formatter = [NSNumberFormatter new];
[formatter setMinimumSignificantDigits:1];
[formatter setMaximumSignificantDigits:1];
[formatter setUsesSignificantDigits:YES];
}
return [[formatter numberFromString:[formatter stringFromNumber:number]] intValue];
}
Yes, this uses objects, but I think that this will be your best bet in the long run, as it handles rounding, parsing, etc. for you.
There is a NSDecimalNumber and NSDecimalNumberHandler classes which does just that. You can define to which precision and to which direction the numbers should be rounded.
Simple example might be:
NSDecimalNumber *dn = [NSDecimalNumber decimalNumberWithMatnissa:294729172258 exponent:-3 isNegative:NO];
NSDecimalNumberHandler *dnh = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:-6 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES];
NSDecimalNumber *rounded = [dn decimalNumberByRoundingAccordingToBehavior:dnh];
This would probably work for your biggest number.

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)