在 C/C++ 中, 直接利用 (x + y) >> 1
来计算
(x + y + 1) >> 1
来计算
(x + y) >> 1
和
(x + y + 1) >> 1
中的
x + y
可能会发生数值溢出. 而
注: 本文假设符号数的右移运算符进行的是算术右移, 符号数的编码方式采用的是 two's complement 编码.
方式一
利用如下公式
下面是对上述两式的证明:
其中
借用上面的公式可以将
(x >> 1) + (y >> 1) + (x & y & 1);
可以将
(x >> 1) + (y >> 1) + ((x | y) & 1);
这两段代码都不会发生数值溢出.
方式二
设 x 和 y 只能取 0 和 1 值, 则:
![496deb2aff936c92078f4afe5b22b442.png](https://i-blog.csdnimg.cn/blog_migrate/111b580d9dc50b9eb940cf592b2d77cc.png)
注意上表中的 10 是二进制下的 10, 即十进制下的 2, & 是逻辑与操作, | 是逻辑或运算, ^ 是逻辑异或操作.
由上表可见 x + y = 2*(x & y) + (x ^ y) = 2*(x | y) - (x ^ y)
.
无符号整型
对于无符号整型, 设
上式用 C/C++语言可以表示为:
(x & y) + ((x ^ y) >> 1);
上式用 C/C++ 语言可以表示为:
(x | y) - ((x ^ y) >> 1);
有符号整型
对于有符号整型, 设
上式用 C/C++ 语言可以表示为:
(x & y) + ((x ^ y) >> 1);
上式用 C/C++ 语言可以表示为:
(x | y) - ((x ^ y) >> 1);
综合
综合上面的分析, 可见对于有符号整型和无符号整型,
(x & y) + ((x ^ y) >> 1);
(x | y) - ((x ^ y) >> 1);
参考
https://stackoverflow.com/questions/24920503/what-is-the-right-way-to-find-the-average-of-two-valuesstackoverflow.com https://stackoverflow.com/questions/3816446/how-can-i-safely-average-two-unsigned-ints-in-cstackoverflow.com版权声明
版权声明:自由分享,保持署名-非商业用途-非衍生,知识共享3.0协议。
如果你对本文有疑问或建议,欢迎留言!转载请保留版权声明!