roundingavravr-gccunsigned-integerfloor

unsigned integer devision rounding AVR GCC


I am struggling to understand how to divide an unsigned integer by a factor of 10 accounting for rounding like a float would round.

uint16_t val = 331 / 10; // two decimal to one decimal places 3.31 to 3.3

uint16_t val = 329 / 10; // two decimal to one decimal places 3.29 to 3.3 (not 2.9)

I would like both of these sums to round to 33 (3.3 in decimal equivalent of 1 decimal place)

Im sure the answer is simple if i were more knowledgable than i am on how processors perform integer division.


Solution

  • Since integer division rounds the result downward to zero, just add half of the divisor, whatever it is. I.e.:

    uint16_t val = ((uint32_t)x + 5) / 10; // convert to 32-bit to avoid overflow

    or in more general form:

    static inline uint16_t divideandround(uint16_t quotient, uint16_t divisor) {
      return ((uint32_t)quotient + (divisor >> 1)) / divisor;
    }
    

    If you are sure there will no 16-bit overflow (i.e. values will always be not more than 65530) you can speed up the calculation by keeping values 16 bit:

    uint16_t val = (x + 5) / 10;