I recently learned that integer overflow is an undefined behavior in C (side question - is it also UB in C++?)
Often in C programming you need to find the average of two values a
and b
. However doing (a+b)/2
can result in overflow and undefined behavior.
So my question is - what is the right way to find the average of two values a
and b
in C?
The mean is what you typically think as the average - found by sum all values and dividing the sum by the number of values. The median is the middle value of the set (or the average of the two middle values if the set is even).
There are three main types of average: mean, median and mode. Each of these techniques works slightly differently and often results in slightly different typical values. The mean is the most commonly used average. To get the mean value, you add up all the values and divide this total by the number of values.
With help from Secure Coding
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
((si_b < 0) && (si_a < (INT_MIN - si_b))))
{
/* will overflow, so use difference method */
return si_b + (si_a - si_b) / 2;
}
else
{
/* the addition will not overflow */
return (si_a + si_b) / 2;
}
ADDENDUM
Thanks to @chux for pointing out the rounding problem. Here's a version that's tested for correct rounding...
int avgnoov (int si_a, int si_b)
{
if ((si_b > 0) && (si_a > (INT_MAX - si_b)))
{
/* will overflow, so use difference method */
/* both si_a and si_b > 0;
we want difference also > 0
so rounding works correctly */
if (si_a >= si_b)
return si_b + (si_a - si_b) / 2;
else
return si_a + (si_b - si_a) / 2;
}
else if ((si_b < 0) && (si_a < (INT_MIN - si_b)))
{
/* will overflow, so use difference method */
/* both si_a and si_b < 0;
we want difference also < 0
so rounding works correctly */
if (si_a <= si_b)
return si_b + (si_a - si_b) / 2;
else
return si_a + (si_b - si_a) / 2;
}
else
{
/* the addition will not overflow */
return (si_a + si_b) / 2;
}
}
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