I would like to round a double to the nearest integer. The function round() returns a double, but I need an actual int. I am afraid that if I do something like (int) round(4.7), the closest float to 5 may be 4.999999999, which the typecast to int would truncate to 4.
What is a good way of rounding to the nearest int?
First of all, you use the data type int, which cannot hold fractional values (and will implicitly round them towards zero, even before the function is ever called.) You should use double instead, since this is the proper datatype for fractional numbers.
You would also want to use the ceil(x) function, which gives the nearest whole number larger than or equal to x.
#include <math.h>
double calculateCharges(double hours)
{
if (hours <= 3) {
return 2.00;
} else {
// return $2.00 for the first 3 hours,
// plus an additional $0.50 per hour begun after that
return 2.00 + ceil(hours - 3) * 0.50;
}
}
To answer your query, you should study your variable type. You use hours as a in, but you return a 2.00 which is a floating number( aka not a integer)
#include <math.h>
double calculateCharge(double hours)
{
//To use accurately the ceil function from Math, the parameter should be a double!
double calculateTime = ( hours <3) ? 2 : (2+ceil(hours-3)*0.50);
return calculateTime;
}
Include the math.h header to be able to use the Math struc. It is a really help structure when you have to compute values, you can calculate the sinus of a number for instance. In our situation, the ceil function will always return the value to round up to the nearest integer. You can learn more about it here : http://www.techonthenet.com/c_language/standard_library_functions/math_h/ceil.php Oh and also, you said less than three hours, but in your function you say less or equals to 3. Make sure you actually use the good operator or you could end up with results you are not expecting while running your function!
Oh, you can look up the ternary operator there in order to have a better understanding of it since it's a bit obscure the first time :http://msdn.microsoft.com/en-us/library/ty67wk28.aspx
Hope it helps you :)
Videos
To round a float in C, there are 3 <math.h> functions to meet the need. Recommend rintf().
float nearbyintf(float x);
The
nearbyintfunctions round their argument to an integer value in floating-point format, using the current rounding direction and without raising the โโinexactโโ floating point exception. C11dr ยง7.12.9.3 2
or
float rintf(float x);
The
rintfunctions differ from thenearbyintfunctions (7.12.9.3) only in that therintfunctions may raise the โโinexactโโ floating-point exception if the result differs in value from the argument. C11dr ยง7.12.9.4 2
or
float roundf(float x);
The
roundfunctions round their argument to the nearest integer value in floating-point format, rounding halfway cases away from zero, regardless of the current rounding direction. C11dr ยง7.12.9.6 2
Example
#include <fenv.h>
#include <math.h>
#include <stdio.h>
void rtest(const char *fname, double (*f)(double x), double x) {
printf("Clear inexact flag :%s\n", feclearexcept(FE_INEXACT) ? "Fail" : "Success");
printf("Set round to nearest mode:%s\n", fesetround(FE_TONEAREST) ? "Fail" : "Success");
double y = (*f)(x);
printf("%s(%f) --> %f\n", fname,x,y);
printf("Inexact flag :%s\n", fetestexcept(FE_INEXACT) ? "Inexact" : "Exact");
puts("");
}
int main(void) {
double x = 8.5;
rtest("nearbyint", nearbyint, x);
rtest("rint", rint, x);
rtest("round", round, x);
return 0;
}
Output
Clear inexact flag :Success
Set round to nearest mode:Success
nearbyint(8.500000) --> 8.000000
Inexact flag :Exact
Clear inexact flag :Success
Set round to nearest mode:Success
rint(8.500000) --> 8.000000
Inexact flag :Inexact
Clear inexact flag :Success
Set round to nearest mode:Success
round(8.500000) --> 9.000000
Inexact flag :Exact
What is weak about OP's code?
(int)(num < 0 ? (num - 0.5) : (num + 0.5))
Should
numhave a value not near theintrange, the cast(int)results in undefined behavior.When
num +/- 0.5results in an inexact answer. This is unlikely here as0.5is adoublecausing the addition to occur at a higher precision thanfloat. Whennumand0.5have the same precision, adding0.5to a number may result in numerical rounded answer. (This is not the whole number rounding of OP's post.) Example: the number just less than 0.5 should round to 0 per OP's goal, yetnum + 0.5results in an exact answer between 1.0 and the smallestdoublejust less than 1.0. Since the exact answer is not representable, that sum rounds, typically to 1.0 leading to an incorrect answer. A similar situation occurs with large numbers.
OP's dilemma about "The above line always prints the value as 4 even when float num =4.9." is not explainable as stated. Additional code/information is needed. I suspect OP may have used int num = 4.9;.
// avoid all library calls
// Relies on UINTMAX_MAX >= FLT_MAX_CONTINUOUS_INTEGER - 1
float my_roundf(float x) {
// Test for large values of x
// All of the x values are whole numbers and need no rounding
#define FLT_MAX_CONTINUOUS_INTEGER (FLT_RADIX/FLT_EPSILON)
if (x >= FLT_MAX_CONTINUOUS_INTEGER) return x;
if (x <= -FLT_MAX_CONTINUOUS_INTEGER) return x;
// Positive numbers
// Important: _no_ precision lost in the subtraction
// This is the key improvement over OP's method
if (x > 0) {
float floor_x = (float)(uintmax_t) x;
if (x - floor_x >= 0.5) floor_x += 1.0f;
return floor_x;
}
if (x < 0) return -my_roundf(-x);
return x; // x is 0.0, -0.0 or NaN
}
Tested little - will do so later when I have time.
4.9 + 0.5 is 5.4, which cannot possibly round to 4 unless your compiler is seriously broken.
I just confirmed that the Googled code gives the correct answer for 4.9.
marcelo@macbookpro-1:~$ cat round.c
#include <stdio.h>
int main() {
float num = 4.9;
int n = (int)(num < 0 ? (num - 0.5) : (num + 0.5));
printf("%d\n", n);
}
marcelo@macbookpro-1:~$ make round && ./round
cc round.c -o round
5
marcelo@macbookpro-1:~$
The standard idiom for integer rounding up is:
int a = (59 + (4 - 1)) / 4;
You add the divisor minus one to the dividend.
A code that works for any sign in dividend and divisor:
int divRoundClosest(const int n, const int d)
{
return ((n < 0) == (d < 0)) ? ((n + d/2)/d) : ((n - d/2)/d);
}
In response to a comment "Why is this actually working?", we can break this apart. First, observe that n/d would be the quotient, but it is truncated towards zero, not rounded. You get a rounded result if you add half of the denominator to the numerator before dividing, but only if numerator and denominator have the same sign. If the signs differ, you must subtract half of the denominator before dividing. Putting all that together:
(n < 0)is false (0) ifnis non-negative(d < 0)is false (0) ifdis non-negative((n < 0) == (d < 0))is true ifnanddhave the same sign(n + d/2)/dis the rounded quotient whennanddhave the same sign(n - d/2)/dis the rounded quotient whennanddhave opposite signs
If you prefer a macro:
#define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) == ((d) < 0)) ? (((n) + (d)/2)/(d)) : (((n) - (d)/2)/(d)))
The linux kernel DIV_ROUND_CLOSEST macro doesn't work for negative divisors!
Hello guys, I am new to programming and I am stuck at rounding up an integer division because when i do 5 / 2 it automatically rounds down but not up... and using int n = round(5 /2) doesnโt work...
Sorry for the stupid question!!!! Still trying to get used to thinking in C...