This feels like a basic question but I couldn't find a definitive answer so far.
I would like to implement an efficient function round_to_nearest(int x, int multiple)
, that rounds a signed integer x
to the nearest multiple of multiple
, avoiding using floating point arithmetic if possible.
Example output:
round_to_nearest(14, 5);
15
round_to_nearest(16, 5);
15
round_to_nearest(23, 5);
25
round_to_nearest(22, 5);
20
round_to_nearest(-23, 5);
-25
round_to_nearest(-22, 5);
-20
The MROUND function rounds a number to the nearest given multiple. The multiple to use for rounding is provided as the significance argument. If the number is already an exact multiple, no rounding occurs and the original number is returned.
Whenever you want to round a number to a particular digit, look only at the digit immediately to its right. For example, if you want to round to the nearest tenth, look to the right of the tenths place: This would be the hundredths place digit. Then, if it is 5 or higher, you get to add one to the tenths digit.
Integer division truncates in C, yes. (i.e. it's round towards zero, not round down.) round toward 0 meaning . 5 or greater => round up 0 to .
In integer arithmetic, if n is positive, add m/2, else subtract m/2, then divide by m (truncating integer divide), then multiply by m:
int round_to_nearest( int n, int m )
{
return (( n + ((n < 0) ? -m : m) / 2) / m ) * m ;
}
int main()
{
int test[] = {16, 23, 22, -23, -22} ;
int m = 5 ;
for( int i = 0; i < sizeof(test) / sizeof(*test); i++ )
{
printf(" round_to_nearest( %d, %d ) = %d\n", test[i], m,
round_to_nearest( test[i], m ) ) ;
}
return 0;
}
Output of test:
round_to_nearest( 16, 5 ) = 15
round_to_nearest( 23, 5 ) = 25
round_to_nearest( 22, 5 ) = 20
round_to_nearest( -23, 5 ) = -25
round_to_nearest( -22, 5 ) = -20
One caveat is that m must be > 0 - which in this context makes sense, I would accept that as a precondition for correct operation; checking for it as a runtime error is probably unnecessary, but you might include an assert to protect against programmer semantic error:
assert( m > 0 ) ;
Standard library asserts are removed when NDEBUG
is defined - normally when debug support is disabled.
For positive numbers:
multiple
to x
multiple
to get the final answerFor negative numbers, the first step is a subtraction, instead of addition.
int round_to_nearest(int x, int multiple)
{
if (x >= 0)
return ((x + multiple / 2) / multiple) * multiple;
else
return ((x - multiple / 2) / multiple) * multiple;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With