什么是找到两个值的平均值的正确方法? [英] What is the right way to find the average of two values?
问题描述
我最近才知道,整数溢出是C中的未定义行为(方的问题 - 是它也UB在C ++中)
I recently learned that integer overflow is an undefined behavior in C (side question - is it also UB in C++?)
经常在C语言编程,你需要找到两个值 A
和 B
的平均值。但是这样做(A + B)/ 2
可导致溢出和不确定的行为。
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.
所以我的问题是 - 什么是找到两个值的平均值的正确方法 A
和 B
中C 3
So my question is - what is the right way to find the average of two values a
and b
in C?
推荐答案
与<帮助href=\"https://www.securecoding.cert.org/confluence/display/sec$c$c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow\"相对=nofollow>安全编码
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;
}
附录
感谢@chux您指出的四舍五入问题。下面是对正确的舍入测试版本...
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;
}
}
这篇关于什么是找到两个值的平均值的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!