A right shift is a division with floor rounding. In order to correctly round you need to add half the divider to the start value.
value = (value+8)>>4
Is this true for negative values? :popcorn:
Good point.
It rounds halfway upwards, which is towards zero for negative values.
One needs to subtract half the divisor for negative values for rounding halfway away from zero; i.e.
value = (value < 0) ? ((value - 8) >> 4) : ((value + 8) >> 4);Note that this applies to all division operations, not just arithmetic shift right:
value = (n < 0) ? (n - d/2) / d : (n + d/2) / d;This even works for negative divisors
d, noting that the addend (
±d/2, which I typically call
half) has the same sign as the divisor if
n is positive, negated if
n is negative.
For integer calculations, this works best when
half itself is truncated towards zero (no rounding applied), so that looking at the results of all possible numerators, you'll have
|d| zero results centered at
n=0 (
|d|-1 if
|d| is even), and then
|d| consecutive same results in both directions. For example, for
d=3,
(n < 0) ? (n-1)/3 : (n+1)/3 yields results -3, -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3 for
n=-8..+8. For
d=4,
(n<0) ? (n-2)/4 : (n+2)/4 yields -2, -1, -1, -1, -1, 0, 0, 0, 1, 1, 1, 1, 2 for
n=-6..+6.
For a sequence of values, you add the
half to the
sum, not to each term:
sum = t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10 + t11 + t12 + t13 + t14 + t15 + t16; avg = (sum < 0) ? (sum - 8)/16 : (sum + 8)/16;Mathematically,
$$\left\lceil \frac{1}{N} \sum_{i=1}^N t_i \right\rfloor = \left\lfloor \frac{1}{N} \left( H + \sum_{i=1}^N t_i \right) \right \rfloor, \quad H = \pm \left\lfloor \frac{N}{2} \right\rfloor$$
where \$H\$ is negated if and only if the sum is negative.
If you do the division and rounding
first, you lose precision, and introduce excess rounding error. It is easiest to understand if you consider decimal numbers rounded to nearest integer. \$\lceil 0.3 + 0.3 + 0.3 + 0.3 + 0.3 + 0.3 \rfloor = 2\$, but \$\lceil 0.3 \rfloor + \lceil 0.3 \rfloor + \lceil 0.3 \rfloor + \lceil 0.3 \rfloor + \lceil 0.3 \rfloor + \lceil 0.3 \rfloor = 0\$.