iOS round a float - objective-c

I have a floating point number that have more decimal digits, for example:
float fRes = 10.0 / 3.0;
actually the fRes value is 3.3333333333333
it's possible set for example 2 decimal digits:
float fRes = 10.0 / 3.0;
// fRes is 3.333333333333333333333333
float fResOk = FuncRound( fRes, 2 );
// fResOk is 3.33
thanks in advance

I don't know where you are using this rounded number, but you should only round your value when displaying it to the user, there are C based format string ways to round floating point numbers for example
[NSString stringWithFormat:#"%.2f", value];
as you may have already read, floating point number are approximations of real numbers, so doing fResOk = roundf( fRes*100.0)/100.0; may not give you 3.33 but a number which is just as close as you can get with floating point number to 3.33.

Assuming that you're looking for the correct function to round to a certain number of digits, you'll probably find it easiest to do the following:
fResOk = roundf( fRes*100.0)/100.0;
That will multiply the value by 100 (giving you your 2 digits of significance), round the value, and then reduce it back to the magnitude you originally started with.

Related

Rounding issue when using NSString and %f [duplicate]

I have a floating point number that have more decimal digits, for example:
float fRes = 10.0 / 3.0;
actually the fRes value is 3.3333333333333
it's possible set for example 2 decimal digits:
float fRes = 10.0 / 3.0;
// fRes is 3.333333333333333333333333
float fResOk = FuncRound( fRes, 2 );
// fResOk is 3.33
thanks in advance
I don't know where you are using this rounded number, but you should only round your value when displaying it to the user, there are C based format string ways to round floating point numbers for example
[NSString stringWithFormat:#"%.2f", value];
as you may have already read, floating point number are approximations of real numbers, so doing fResOk = roundf( fRes*100.0)/100.0; may not give you 3.33 but a number which is just as close as you can get with floating point number to 3.33.
Assuming that you're looking for the correct function to round to a certain number of digits, you'll probably find it easiest to do the following:
fResOk = roundf( fRes*100.0)/100.0;
That will multiply the value by 100 (giving you your 2 digits of significance), round the value, and then reduce it back to the magnitude you originally started with.

Objective-C: floorf( ) returns wrong value

Here is the code:
float passedPrice = 2.953;
float placed = 1000.0; //3 decimals
NSLog("%f", placed); // Gives 2953;
float withNoFractions = floorf(passedPrice * placed);
The value stored in withNoFractions is 2952! It shall be 2953. What is really strange is that it works some time.
Many decimal floating point fractions cannot be represented as exact fractions in binary, so they have to be approximated. 2.953 is being approximated as something like 2.95299999. When you multiply by 1000, the result is 2952.99999, and when you get the floor of this, it's 2952.
To solve this, you can either use round() instead of ffloorf(), or you can add 0.5 before calling ffloorf():
float withNoFractions = floorf(passedPrice * placed + 0.5);

Returning a number less than 1

I am working on an app that needs to utilize a ratio of a given number and multiply that ratio times another number. Problem is that I can't get numbers less that 1 to give me the proper decimal ratio, instead it gives me zero (when it should be .5).
Example:
float number = 1/2; // This gives me zero
double number = 1/2; // This also gives me zero
If you don't specify decimal places you're using integers which means the calculation is performed with integer precision before the result is cast to the type on the LHS. You want to do the the following when using hard coded numbers in your code:
float number = 1.0f / 2.0f;
double number = 1.0 / 2.0;
If you're aiming to use integer variables for an operation, you'll want to cast them to the type that you want for your result.
Try this
float number = 1.0/2.0;
Remember that 1 is an int, so you are essentially taking
(int)1 / (int)2
which returns
(int)0
To cast variables that are ints, do
float number = (float)numerator / (float)denominator;

Objective-C: Strange calculation result

I am learning Objective-C and have completed a simple program and got an unexpected result. This program is just a multiplication table test... User inputs the number of iterations(test questions), then inputs answers. That after program displays the number of right and wrong answers, percentage and accepted/failed result.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Welcome to multiplication table test");
int rightAnswers; //the sum of the right answers
int wrongAnswers; //the sum of wrong answers
int combinations; //the number of combinations#
NSLog(#"Please, input the number of test combinations");
scanf("%d",&combinations);
for(int i=0; i<combinations; ++i)
{
int firstInt=rand()%8+1;
int secondInt=rand()%8+1;
int result=firstInt*secondInt;
int answer;
NSLog(#"%d*%d=",firstInt,secondInt);
scanf("%d",&answer);
if(answer==result)
{
NSLog(#"Ok");
rightAnswers++;
}
else
{
NSLog(#"Error");
wrongAnswers++;
}
}
int percent=(100/combinations)*rightAnswers;
NSLog(#"Combinations passed: %d",combinations);
NSLog(#"Answered right: %d times",rightAnswers);
NSLog(#"Answered wrong: %d times",wrongAnswers);
NSLog(#"Completed %d percent",percent);
if(percent>=70)NSLog(#"accepted");
else
NSLog(#"failed");
[pool drain];
return 0;
}
Problem (strange result)
When I input 3 iterations and answer 'em right, i am not getting of 100% right. Getting only
99%. The same count I tried on my iPhone calculator.
100 / 3 = 33.3333333... percentage for one right answer (program displays 33%. The digits after mantissa getting cut off)
33.3333333... * 3=100%
Can someone explain me where I went wrong? Thanx.
This is a result of integer division. When you perform division between two integer types, the result is automatically rounded towards 0 to form an integer. So, integer division of (100 / 3) gives a result of 33, not 33.33.... When you multiply that by 3, you get 99. To fix this, you can force floating point division by changing 100 to 100.0. The .0 tells the compiler that it should use a floating point type instead of an integer, forcing floating point division. As a result, rounding will not occur after the division. However, 33.33... cannot be represented exactly by binary numbers. Because of this, you may still see incorrect results at times. Since you store the result as an integer, rounding down will still occur after the multiplication, which will make it more obvious. If you want to use an integer type, you should use the round function on the result:
int percent = round((100.0 / combinations) * rightAnswers);
This will cause the number to be rounded to the closest integer before converting it to an integer type. Alternately, you could use a floating point storage type and specify a certain number of decimal places to display:
float percent = (100.0 / combinations) * rightAnswers;
NSLog(#"Completed %.1f percent",percent); // Display result with 1 decimal place
Finally, since floating point math will still cause rounding for numbers that can't be represented in binary, I would suggest multiplying by rightAnswers before dividing by combinations. This will increase the chances that the result is representable. For example, 100/3=33.33... is not representable and will be rounded. If you multiply by 3 first, you get 300/3=100, which is representable and will not be rounded.
Ints are integers. They can't represent an arbitrary real number like 1/3. Even floating-point numbers, which can represent reals, won't have enough precision to represent an infinitely repeating decimal like 100/3. You'll either need to use an arbitrary-precision library, use a library that includes rationals as a data type, or just store as much precision as you need and round from there (e.g. make your integer unit hundredths-of-a-percent instead of a single percentage point).
You might want to implement some sort of rounding because 33.333....*3 = 99.99999%. 3/10 is an infinite decimal therefore you need some sort of rounding to occur (maybe at the 3rd decimal place) so that the answer comes out correct. I would say if (num*1000 % 10 >= 5) num += .01 or something along those lines multiply by 100 moves decimal 3 times and then mod returns the 3rd digit (could be zero). You also might only want to round at the end once you sum everything up to avoid errors.
EDIT: Didn't realize you were using integers numbers at the end threw me off, you might want to use double or float (floats are slightly inaccurate past 2 or 3 digits which is OK with what you want).
100/3 is 33. Integer mathematics here.

NSTimeInterval to readable NSNumber

NSTimeInterval == double; (e.g. 169.12345666663)
How can I round up this double so that there are only 2 digits left after the "dot"?
It would be very good if the result is a NSNumber.
If this is for display purposes, take a look at NSNumberFormatter.
If you really want to round the double in your calculations for some reason, you can use the standard C round() function.
A NSDecimal can be rounded to a specified number of digits with NSDecimalRound().
double d = [[NSDate date] timeIntervalSince1970];
NSDecimal in = [[NSNumber numberWithDouble:d] decimalValue];
NSDecimal out;
NSDecimalRound( &out, &in, 2, NSRoundUp );
NSDecimalNumber *result = [NSDecimalNumber decimalNumberWithDecimal:out];
If you really want two digits left after the dot, multiply by 100, round it using round() function, divide it by 100 again. However, this will not guarantee that it really has only two digits after the dot, since by dividing it again, you may get a number that cannot really be expressed with floating point notation and when you expect 0.1 you may in fact get 0.09999..., that's because you cannot really express 0.1 using floating point notation.
If you just want to round it to two digits after the dot for display purposes, you can use NSNumberFormatter as has been suggested or just use:
printf("%.2f\n", yourTimeInterval);
NSLog(#"%.2f\n", yourTimeInterval);
or to get an NSString, you can also use the following, which is probably even faster than using a NumberFormatter (however, it won't be localized according to the user prefs):
NSString * intervalStr = nil;
char * intervalStrTmp = NULL;
asprintf(&intervalStrTmp, "%.2f", yourTimeInteval);
if (intervalStrTmp) {
intervalStr = [[NSString alloc] initWithUTF8String:intervalStrTmp];
free(intervalStrTmp);
}
In the vast majority of cases rounding a number is something you should only do at display time. The properties of floating-point numbers (double or not) make it impossible to store certain numbers at a fixed-precision.
For information about formatting a number so it displays to two decimal places, see this other post.
Does this HumanReadableTimeInterval help? It returns a NSString, though.
Alternatively, you can round yourself by multiplying with 100, converting to an integer and dividing through 100 again.
I would just use the ANSI C round() function.
You can always round the number using:
double round2dec(double a) { return round(a * 100) / 100; }
But chances are that the representation of the result as a double will not have only 2 decimals.
Now, if by using the == sign, you meant that the comparison of your two double numbers is made only to the second decimal. Here is what you can do:
fabs(round2dec(NSTimeInterval) - round2dec(double)) < std::numeric_limits<double>::epsilon()