四舍五入整数除法(而不是截断)

我很好奇怎样才能把一个数舍入到最接近的整数。例如,如果我有:

int a = 59 / 4;

如果以浮点数计算,则为14.75; 如何将结果存储为“ a”中的15?

194036 次浏览

The standard idiom for integer rounding up is:

int a = (59 + (4 - 1)) / 4;

You add the divisor minus one to the dividend.

int a = 59.0f / 4.0f + 0.5f;

This only works when assigning to an int as it discards anything after the '.'

Edit: This solution will only work in the simplest of cases. A more robust solution would be:

unsigned int round_closest(unsigned int dividend, unsigned int divisor)
{
return (dividend + (divisor / 2)) / divisor;
}

As written, you're performing integer arithmetic, which automatically just truncates any decimal results. To perform floating point arithmetic, either change the constants to be floating point values:

int a = round(59.0 / 4);

Or cast them to a float or other floating point type:

int a = round((float)59 / 4);

Either way, you need to do the final rounding with the round() function in the math.h header, so be sure to #include <math.h> and use a C99 compatible compiler.

You should instead use something like this:

int a = (59 - 1)/ 4 + 1;

I assume that you are really trying to do something more general:

int divide(x, y)
{
int a = (x -1)/y +1;


return a;
}

x + (y-1) has the potential to overflow giving the incorrect result; whereas, x - 1 will only underflow if x = min_int...

int divide(x,y){
int quotient = x/y;
int remainder = x%y;
if(remainder==0)
return quotient;
int tempY = divide(y,2);
if(remainder>=tempY)
quotient++;
return quotient;
}

eg 59/4 Quotient = 14, tempY = 2, remainder = 3, remainder >= tempY hence quotient = 15;

#define CEIL(a, b) (((a) / (b)) + (((a) % (b)) > 0 ? 1 : 0))

Another useful MACROS (MUST HAVE):

#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
#define ABS(a)     (((a) < 0) ? -(a) : (a))

From Linux kernel (GPLv2):

/*
* Divide positive or negative dividend by positive divisor and round
* to closest integer. Result is undefined for negative divisors and
* for negative dividends if the divisor variable type is unsigned.
*/
#define DIV_ROUND_CLOSEST(x, divisor)(          \
{                           \
typeof(x) __x = x;              \
typeof(divisor) __d = divisor;          \
(((typeof(x))-1) > 0 ||             \
((typeof(divisor))-1) > 0 || (__x) > 0) ?  \
(((__x) + ((__d) / 2)) / (__d)) :   \
(((__x) - ((__d) / 2)) / (__d));    \
}                           \
)

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 (zero) if n is non-negative
(d < 0) is false (zero) if d is non-negative
((n < 0) ^ (d < 0)) is true if n and d have opposite signs
(n + d/2)/d is the rounded quotient when n and d have the same sign
(n - d/2)/d is the rounded quotient when n and d have 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 macro DIV_ROUND_CLOSEST doesn't work for negative divisors!

(Edited) Rounding integers with floating point is the easiest solution to this problem; however, depending on the problem set is may be possible. For example, in embedded systems the floating point solution may be too costly.

Doing this using integer math turns out to be kind of hard and a little unintuitive. The first posted solution worked okay for the the problem I had used it for but after characterizing the results over the range of integers it turned out to be very bad in general. Looking through several books on bit twiddling and embedded math return few results. A couple of notes. First, I only tested for positive integers, my work does not involve negative numerators or denominators. Second, and exhaustive test of 32 bit integers is computational prohibitive so I started with 8 bit integers and then mades sure that I got similar results with 16 bit integers.

I started with the 2 solutions that I had previously proposed:

#define DIVIDE_WITH_ROUND(N, D) (((N) == 0) ? 0:(((N * 10)/D) + 5)/10)

#define DIVIDE_WITH_ROUND(N, D) (N == 0) ? 0:(N - D/2)/D + 1;

My thought was that the first version would overflow with big numbers and the second underflow with small numbers. I did not take 2 things into consideration. 1.) the 2nd problem is actually recursive since to get the correct answer you have to properly round D/2. 2.) In the first case you often overflow and then underflow, the two canceling each other out. Here is an error plot of the two (incorrect) algorithms:Divide with Round1 8 bit x=numerator y=denominator

This plot shows that the first algorithm is only incorrect for small denominators (0 < d < 10). Unexpectedly it actually handles large numerators better than the 2nd version.

Here is a plot of the 2nd algorithm: 8 bit signed numbers 2nd algorithm.

As expected it fails for small numerators but also fails for more large numerators than the 1st version.

Clearly this is the better starting point for a correct version:

#define DIVIDE_WITH_ROUND(N, D) (((N) == 0) ? 0:(((N * 10)/D) + 5)/10)

If your denominators is > 10 then this will work correctly.

A special case is needed for D == 1, simply return N. A special case is needed for D== 2, = N/2 + (N & 1) // Round up if odd.

D >= 3 also has problems once N gets big enough. It turns out that larger denominators only have problems with larger numerators. For 8 bit signed number the problem points are

if (D == 3) && (N > 75))
else if ((D == 4) && (N > 100))
else if ((D == 5) && (N > 125))
else if ((D == 6) && (N > 150))
else if ((D == 7) && (N > 175))
else if ((D == 8) && (N > 200))
else if ((D == 9) && (N > 225))
else if ((D == 10) && (N > 250))

(return D/N for these)

So in general the the pointe where a particular numerator gets bad is somewhere around
N > (MAX_INT - 5) * D/10

This is not exact but close. When working with 16 bit or bigger numbers the error < 1% if you just do a C divide (truncation) for these cases.

For 16 bit signed numbers the tests would be

if ((D == 3) && (N >= 9829))
else if ((D == 4) && (N >= 13106))
else if ((D == 5) && (N >= 16382))
else if ((D == 6) && (N >= 19658))
else if ((D == 7) && (N >= 22935))
else if ((D == 8) && (N >= 26211))
else if ((D == 9) && (N >= 29487))
else if ((D == 10) && (N >= 32763))

Of course for unsigned integers MAX_INT would be replaced with MAX_UINT. I am sure there is an exact formula for determining the largest N that will work for a particular D and number of bits but I don't have any more time to work on this problem...

(I seem to be missing this graph at the moment, I will edit and add later.) This is a graph of the 8 bit version with the special cases noted above:![8 bit signed with special cases for 0 < N <= 10 3

Note that for 8 bit the error is 10% or less for all errors in the graph, 16 bit is < 0.1%.

For some algorithms you need a consistent bias when 'nearest' is a tie.

// round-to-nearest with mid-value bias towards positive infinity
int div_nearest( int n, int d )
{
if (d<0) n*=-1, d*=-1;
return (abs(n)+((d-(n<0?1:0))>>1))/d * ((n<0)?-1:+1);
}

This works regardless of the sign of the numerator or denominator.


If you want to match the results of round(N/(double)D) (floating-point division and rounding), here are a few variations that all produce the same results:

int div_nearest( int n, int d )
{
int r=(n<0?-1:+1)*(abs(d)>>1); // eliminates a division
// int r=((n<0)^(d<0)?-1:+1)*(d/2); // basically the same as @ericbn
// int r=(n*d<0?-1:+1)*(d/2); // small variation from @ericbn
return (n+r)/d;
}

Note: The relative speed of (abs(d)>>1) vs. (d/2) is likely to be platform dependent.

try using math ceil function that makes rounding up. Math Ceil !

int a, b;
int c = a / b;
if(a % b) { c++; }

Checking if there is a remainder allows you to manually roundup the quotient of integer division.

Borrowing from @ericbn I prefere defines like

#define DIV_ROUND_INT(n,d) ((((n) < 0) ^ ((d) < 0)) ? (((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d)))
or if you work only with unsigned ints
#define DIV_ROUND_UINT(n,d) ((((n) + (d)/2)/(d)))

If you're dividing positive integers you can shift it up, do the division and then check the bit to the right of the real b0. In other words, 100/8 is 12.5 but would return 12. If you do (100<<1)/8, you can check b0 and then round up after you shift the result back down.

Here's my solution. I like it because I find it more readable and because it has no branching (neither ifs nor ternaries).

int32_t divide(int32_t a, int32_t b) {
int32_t resultIsNegative = ((a ^ b) & 0x80000000) >> 31;
int32_t sign = resultIsNegative*-2+1;
return (a + (b / 2 * sign)) / b;
}

Full test program that illustrates intended behaviour:

#include <stdint.h>
#include <assert.h>


int32_t divide(int32_t a, int32_t b) {
int32_t resultIsNegative = ((a ^ b) & 0x80000000) >> 31;
int32_t sign = resultIsNegative*-2+1;
return (a + (b / 2 * sign)) / b;
}


int main() {
assert(divide(0, 3) == 0);


assert(divide(1, 3) == 0);
assert(divide(5, 3) == 2);


assert(divide(-1, 3) == 0);
assert(divide(-5, 3) == -2);


assert(divide(1, -3) == 0);
assert(divide(5, -3) == -2);


assert(divide(-1, -3) == 0);
assert(divide(-5, -3) == 2);
}

I ran into the same difficulty. The code below should work for positive integers.

I haven't compiled it yet but I tested the algorithm on a google spreadsheet (I know, wtf) and it was working.

unsigned int integer_div_round_nearest(unsigned int numerator, unsigned int denominator)
{
unsigned int rem;
unsigned int floor;
unsigned int denom_div_2;


// check error cases
if(denominator == 0)
return 0;


if(denominator == 1)
return numerator;


// Compute integer division and remainder
floor = numerator/denominator;
rem = numerator%denominator;


// Get the rounded value of the denominator divided by two
denom_div_2 = denominator/2;
if(denominator%2)
denom_div_2++;


// If the remainder is bigger than half of the denominator, adjust value
if(rem >= denom_div_2)
return floor+1;
else
return floor;
}

Safer C code (unless you have other methods of handling /0):

return (_divisor > 0) ? ((_dividend + (_divisor - 1)) / _divisor) : _dividend;

This doesn't handle the problems that occur from having an incorrect return value as a result of your invalid input data, of course.

double a=59.0/4;
int b=59/4;
if(a-b>=0.5){
b++;
}
printf("%d",b);
  1. let exact float value of 59.0/4 be x(here it is 14.750000)
  2. let smallest integer less than x be y(here it is 14)
  3. if x-y<0.5 then y is the solution
  4. else y+1 is the solution

The following correctly rounds the quotient to the nearest integer for both positive and negative operands WITHOUT floating point or conditional branches (see assembly output below). Assumes N-bit 2's complement integers.

#define ASR(x) ((x) < 0 ? -1 : 0)  // Compiles into a (N-1)-bit arithmetic shift right
#define ROUNDING(x,y) ( (y)/2 - (ASR((x)^(y)) & (y)))


int RoundedQuotient(int x, int y)
{
return (x + ROUNDING(x,y)) / y ;
}

The value of ROUNDING will have the same sign as the dividend (x) and half the magnitude of the divisor (y). Adding ROUNDING to the dividend thus increases its magnitude before the integer division truncates the resulting quotient. Here's the output of the gcc compiler with -O3 optimization for a 32-bit ARM Cortex-M4 processor:

RoundedQuotient:                // Input parameters: r0 = x, r1 = y
eor     r2, r1, r0          // r2 = x^y
and     r2, r1, r2, asr #31 // r2 = ASR(x^y) & y
add     r3, r1, r1, lsr #31 // r3 = (y < 0) ? y + 1 : y
rsb     r3, r2, r3, asr #1  // r3 = y/2 - (ASR(x^y) & y)
add     r0, r0, r3          // r0 = x + (y/2 - (ASR(x^y) & y)
sdiv    r0, r0, r1          // r0 = (x + ROUNDING(x,y)) / y
bx      lr                  // Returns r0 = rounded quotient

Some alternatives for division by 4

return x/4 + (x/2 % 2);
return x/4 + (x % 4 >= 2)

Or in general, division by any power of 2

return x/y + x/(y/2) % 2;    // or
return (x >> i) + ((x >> i - 1) & 1);  // with y = 2^i

It works by rounding up if the fractional part ⩾ 0.5, i.e. the first digit ⩾ base/2. In binary it's equivalent to adding the first fractional bit to the result

This method has an advantage in architectures with a flag register, because the carry flag will contain the last bit that was shifted out. For example on x86 it can be optimized into

shr eax, i
adc eax, 0

It's also easily extended to support signed integers. Notice that the expression for negative numbers is

(x - 1)/y + ((x - 1)/(y/2) & 1)

we can make it work for both positive and negative values with

int t = x + (x >> 31);
return (t >> i) + ((t >> i - 1) & 1);

Update 2 May 2021:

The code in my original answer below is for positive integers only. To handle proper rounding for negative integers too, see the techniques in my project repo here: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/c/rounding_integer_division. Main file: rounding_integer_division.cpp.

It contains:

  1. These C or C++ macros:
    DIVIDE_ROUNDUP(numer, denom)
    DIVIDE_ROUNDDOWN(numer, denom)
    DIVIDE_ROUNDNEAREST(numer, denom)
    
  2. These gcc/clang C or C++ statement expressions (safer than macros):
    DIVIDE_ROUNDUP2(numer, denom)
    DIVIDE_ROUNDDOWN2(numer, denom)
    DIVIDE_ROUNDNEAREST2(numer, denom)
    
  3. These C++ templates:
    template <typename T>
    T divide_roundup(T numer, T denom)
    
    
    template <typename T>
    T divide_rounddown(T numer, T denom)
    
    
    template <typename T>
    T divide_roundnearest(T numer, T denom)
    
  4. A bunch of unit tests to test all of the above.

ORIGINAL ANSWER:

Summary: Here's a macro you can use

// (Works for **positive** integers only! See above for fully-robust
// options instead.)
// To do (numer/denom), rounded to the nearest whole integer, use:
#define ROUND_DIVIDE(numer, denom) (((numer) + (denom) / 2) / (denom))

Usage example:

int num = ROUND_DIVIDE(13,7); // 13/7 = 1.857 --> rounds to 2, so num is 2

Full answer:

Some of these answers are crazy looking! Codeface nailed it though! (See @0xC0DEFACE's answer here). I really like the type-free macro or gcc statement expression form over the function form, however, so, I wrote this answer with a detailed explanation of what I'm doing (ie: why this mathematically works) and put it into 2 forms:

1. Macro form, with detailed commentary to explain the whole thing:

/// @brief      ROUND_DIVIDE(numerator/denominator): round to the nearest whole integer when doing
///             *integer* division only
/// @details    This works on *integers only* since it assumes integer truncation will take place automatically
///             during the division!
/// @notes      The concept is this: add 1/2 to any number to get it to round to the nearest whole integer
///             after integer trunction.
///             Examples:  2.74 + 0.5 = 3.24 --> 3 when truncated
///                        2.99 + 0.5 = 3.49 --> 3 when truncated
///                        2.50 + 0.5 = 3.00 --> 3 when truncated
///                        2.49 + 0.5 = 2.99 --> 2 when truncated
///                        2.00 + 0.5 = 2.50 --> 2 when truncated
///                        1.75 + 0.5 = 2.25 --> 2 when truncated
///             To add 1/2 in integer terms, you must do it *before* the division. This is achieved by
///             adding 1/2*denominator, which is (denominator/2), to the numerator before the division.
///             ie: `rounded_division = (numer + denom/2)/denom`.
///             ==Proof==: 1/2 is the same as (denom/2)/denom. Therefore, (numer/denom) + 1/2 becomes
///             (numer/denom) + (denom/2)/denom. They have a common denominator, so combine terms and you get:
///             (numer + denom/2)/denom, which is the answer above.
/// @param[in]  numerator   any integer type numerator; ex: uint8_t, uint16_t, uint32_t, int8_t, int16_t, int32_t, etc
/// @param[in]  denominator any integer type denominator; ex: uint8_t, uint16_t, uint32_t, int8_t, int16_t, int32_t, etc
/// @return     The result of the (numerator/denominator) division rounded to the nearest *whole integer*!
#define ROUND_DIVIDE(numerator, denominator) (((numerator) + (denominator) / 2) / (denominator))

2. GCC Statement Expression form:

See a little more on gcc statement expressions here.

/// @brief      *gcc statement expression* form of the above macro
#define ROUND_DIVIDE2(numerator, denominator)               \
({                                                          \
__typeof__ (numerator) numerator_ = (numerator);        \
__typeof__ (denominator) denominator_ = (denominator);  \
numerator_ + (denominator_ / 2) / denominator_;         \
})

3. C++ Function Template form:

(Added Mar./Apr. 2020)

#include <limits>


// Template form for C++ (with type checking to ensure only integer types are passed in!)
template <typename T>
T round_division(T numerator, T denominator)
{
// Ensure only integer types are passed in, as this round division technique does NOT work on
// floating point types since it assumes integer truncation will take place automatically
// during the division!
// - The following static assert allows all integer types, including their various `const`,
//   `volatile`, and `const volatile` variations, but prohibits any floating point type
//   such as `float`, `double`, and `long double`.
// - Reference page: https://en.cppreference.com/w/cpp/types/numeric_limits/is_integer
static_assert(std::numeric_limits<T>::is_integer, "Only integer types are allowed");
return (numerator + denominator/2)/denominator;
}

Run & test some of this code here:

  1. OnlineGDB: integer rounding during division

Related Answers:

  1. Fixed Point Arithmetic in C Programming - in this answer I go over how to do integer rounding to the nearest whole integer, then tenth place (1 decimal digit to the right of the decimal), hundredth place (2 dec digits), thousandth place (3 dec digits), etc. Search the answer for the section in my code comments called BASE 2 CONCEPT: for more details!
  2. A related answer of mine on gcc's statement expressions: MIN and MAX in C
  3. The function form of this with fixed types: Rounding integer division (instead of truncating)
  4. What is the behavior of integer division?
  5. For rounding up instead of to nearest integer, follow this similar pattern: Rounding integer division (instead of truncating)

References:

  1. https://www.tutorialspoint.com/cplusplus/cpp_templates.htm

todo: test this for negative inputs & update this answer if it works:

#define ROUND_DIVIDE(numer, denom) ((numer < 0) != (denom < 0) ? ((numer) - (denom) / 2) / (denom) : ((numer) + (denom) / 2) / (denom))

The fundamental rounding divide algorithm, as presented by previous contributors, is to add half the denominator to the numerator before division. This is simple when the inputs are unsigned, not quite so when signed values are involved. Here are some solutions that generate optimal code by GCC for ARM (thumb-2).

Signed / Unsigned

inline int DivIntByUintRnd(int n, uint d)
{
int sgn = n >> (sizeof(n)*8-1); // 0 or -1
return (n + (int)(((d / 2) ^ sgn) - sgn)) / (int)d;
}

The first code line replicates the numerator sign bit through an entire word, creating zero (positive) or -1 (negative). On the second line, this value (if negative) is used to negate the rounding term using 2's complement negation: complement and increment. Previous answers used a conditional statement or multiply to achieve this.

Signed / Signed

inline int DivIntRnd(int n, int d)
{
int rnd = d / 2;
return (n + ((n ^ d) < 0 ? -rnd : rnd)) / d;
}

I found I got the shortest code with the conditional expression, but only if I helped the compiler by computing the rounding value d/2. Using 2's complement negation is close:

inline int DivIntRnd(int n, int d)
{
int sgn = (n ^ d) >> (sizeof(n)*8-1);   // 0 or -1
return (n + ((d ^ sgn) - sgn) / 2) / d;
}

Division by Powers of 2

While integer division truncates toward zero, shifting truncates toward negative infinity. This makes a rounding shift much simpler, as you always add the rounding value regardless of the sign of the numerator.

inline int ShiftIntRnd(int n, int s)        { return ((n >> (s - 1)) + 1) >> 1; }
inline uint ShiftUintRnd(uint n, int s)     { return ((n >> (s - 1)) + 1) >> 1; }

The expression is the same (generating different code based on type), so a macro or overloaded function could work for both.

The traditional method (the way rounding division works) would be to add half the divisor, 1 << (s-1). Instead we shift one less, add one, and then do the final shift. This saves creating a non-trivial value (even if constant) and the machine register to put it in.

For unsigned integer types and positive divider use:

template<typename T> T urounddiv(T n, T d) {
return (n / d) + ((n % d) > (d / 2));
}

Step by step

59 / 4 + ((59 % 4) > (4 / 2))
14 + (3 > 2)
14 + true
14 + 1
15

General case

These C++ function templates work for any integral type T without overflowing, for any positive divider, and without using floating point.
Integer division in C truncates towards zero and so does rounddiv, rounddiv(3, 2) == 1 and rounddiv(-3, 2) == -1. The rounddiv_away function template rounds the half point away from zero, rounddiv_away(3, 2) == 2 and rounddiv_away(-3, 2) == -2. The results are different only when d is even.

// Round to zero division, no overflow
template<typename T> T rounddiv(T n, T d) {
T r = n / d;
T m = n % d;
T h = d / 2;
return r + (!(n < 0) & (m > h)) - ((n < 0) & ((m + h) < 0));
}
// Round away from zero division, no overflow
template<typename T> T rounddiv_away(T n, T d) {
T r = n / d;
T m = n % d;
T h = (d / 2) + (d & 1);
return r + (!(n < 0) & (m >= h)) - ((n < 0) & ((m + h) <= 0));
}

How it works

Start with positive integers. Instead of adding half of the divider to the original number, which is subject to range overflow, compare the remainder of the division (the result of the modulo operation) with half of the divider. If the reminder is larger than half of the divider, round up the result by incrementing it. The reminder value is available as a byproduct of the integer division in most cases, it is not an extra operation.

// Round to zero division of unsigned types, no overflow
template<typename T>
static T rounddiv(T x, T d) {
static_assert(std::is_unsigned<T>(), "Unsigned integer types only");
T r = x / d;
T m = x % d;
T h = d / 2;
if (m > h)
r = r + 1;
return r;
}

For signed types, if x is positive the same formula applies. But when x is negative, both r and m will be negative, with r being truncated towards zero. This means that the result needs to be decremented when the absolute value of the reminder (-m) is larger than half of the quanta.

// Round to zero division, no overflow
template<typename T>
static T rounddiv(T x, T d) {
static_assert(std::is_integral<T>(), "Integer types only");
T r = x / d
T m = x % d;
T h = d / 2;
if ((x >= 0) && (m > h))
r = r + 1;
else if ((x < 0) && (-m > h))
r = r - 1
return r;
}

The rest is just an optimized form to help the compiler generate better code. It is avoiding conditional execution by taking advantage of the fact that the result of a condition is a boolean which becomes 0 (false) or 1 (true) when converted to an integral type. The (m + h) < 0 is an alternate form of -m > h, which some compilers don't like when T is an unsigned type. For unsigned types most of the conditions are constant and will be optimized away.
The rounddiv_away function works similarly, with the conditions adjusted to include the exact middle value.
If the divider d is negative, use: -rounddiv(n, -d) (overflows only when d is minimum possible value for type). Round up (to plus infinity) or round down (to minus infinity) is also possible by combining parts of the two templates above.

If I haven't missed something the answer of cipilo is the only solution which works for all parameter, even close to INT_MAX. It avoids the possible overflow errors of other solutions. I can't comment or up-vote due to lacking reputation.

His implementation handles only positive divisors. My solution considers those overflows as well and handles also negative divisors.

C (as asked):

unsigned round_div_halfawayu(unsigned n, unsigned d)
{
return n / d + (n % d > (d - 1) / 2);
}


int round_div_halfaway(int n, int d)
{
assert(abs(INT_MIN) - 1 == abs(INT_MIN + 1));
if ((n < 0) == (d < 0))
return n / d + (abs(n % d) > (abs(d) - 1) / 2);
else
return n / d - (abs(n % d) > (abs(d) - 1) / 2);
}

C++ (I'm using):

template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
T round_div_halfaway(T n, T d)
{
if constexpr (std::is_unsigned<T>::value)
return n / d + (n % d > (d - 1) / 2);
else if constexpr (std::is_signed<T>::value)
{
assert(std::abs(std::numeric_limits<T>::min()) - 1 ==
std::abs(std::numeric_limits<T>::min() + 1));
if ((n < 0) == (d < 0))
return n / d + (std::abs(n % d) > (std::abs(d) - 1) / 2);
else
return n / d - (std::abs(n % d) > (std::abs(d) - 1) / 2);
}
}

It is basically calculating the truncated result and increases the absolute if neccessary. The assertion checks for the overflow behavior of abs(INT_MIN), which is undefined by the standard.

The function implements the common commercial rounding (half away from zero).

If you use floating point you will round to the nearest even number if two integers are equally close. For example round(5./2.) = 2, while the integer methods provided above gives 5/2 = 3. The round-to-nearest-or-even method is useful for minimizing accumulating rounding errors. See https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even

To do this without using floating point, you have to round away from zero if the remainder is equal to half the divisor and the division result is odd.

This code should work for positive integers:

unsigned int rounded_division(unsigned int n, unsigned int d) {
unsigned int q = n / d;  // quotient
unsigned int r = n % d;  // remainder
if (r > d>>1  // fraction > 0.5
|| (r == d>>1 && (q&1) && !(d&1))) { // fraction == 0.5 and odd
q++;
}
return q;
}