两个unit取和会溢出吗_C/C++之如何计算两个整型的平均值

在 C/C++ 中, 直接利用 (x + y) >> 1 来计算

(两个整数的平均值并向下取整)以及直接利用
(x + y + 1) >> 1 来计算
(两个整数的平均值并向上取整)的结果可能有误, 因为
(x + y) >> 1(x + y + 1) >> 1 中的 x + y 可能会发生数值溢出. 而
的结果是不可能数值溢出的, 这就引发我们思考可不可能通过某种方式来规避平均值计算中的数值溢出.

注: 本文假设符号数的右移运算符进行的是算术右移, 符号数的编码方式采用的是 two's complement 编码.

方式一

利用如下公式

下面是对上述两式的证明:

其中

均为整数.

借用上面的公式可以将

转化为如下的 C/C++ 代码 (据说这段代码还被申请了专利):
(x >> 1) + (y >> 1) + (x & y & 1);

可以将

转化为如下的 C/C++ 代码:
(x >> 1) + (y >> 1) + ((x | y) & 1);

这两段代码都不会发生数值溢出.

方式二

设 x 和 y 只能取 0 和 1 值, 则:

496deb2aff936c92078f4afe5b22b442.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);

有符号整型

对于有符号整型, 设

(这里采用的是符号数的 two's-complement 编码表示), 其中
.

上式用 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);

参考

https://stackoverflow.com/questions/24920503/what-is-the-right-way-to-find-the-average-of-two-values​stackoverflow.com https://stackoverflow.com/questions/3816446/how-can-i-safely-average-two-unsigned-ints-in-c​stackoverflow.com

版权声明

版权声明:自由分享,保持署名-非商业用途-非衍生,知识共享3.0协议。

如果你对本文有疑问或建议,欢迎留言!转载请保留版权声明!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值