《程序员面试宝典》不懂问题一道~

guaner0203 2012-03-04 10:29:34
问题如下:

int f(int x,int y){
return (x&y)+((x^y)>>1);
}

作者的解释是:
X&Y是取相同的位与后的结果是X和Y相同位的一半,x^y是取x和y的不同位,右移相等于除以2,所以这个函数的功能是取两个数的平均值。

这话怎么理解?想不通啊~~
...全文
205 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
guaner0203 2012-03-04
  • 打赏
  • 举报
回复
可是这句话
X&Y是取相同的位与后的结果是X和Y相同位的一半
单拿出来怎么理解呢?
guaner0203 2012-03-04
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 czh3642210 的回复:]

LS括号看错了,引用楼上的测试
x=0001,y=0111(二进制的)
x&y = 0001
x^y = 0110 所以 (x^y)>>1 = 0011
所以
(x&y)+((x^y)>>1) = 0001 + 0011 = 0100
是正确的
[/Quote]

小弟初学者,听了你的解释明白了好多,但是还要再想一想 。
非常感谢~~
xxplili 2012-03-04
  • 打赏
  • 举报
回复
好巧妙的方法
前面的是进位,后面是相加除2。。。
其实就是
((x&y)<<1+(x^y))>>1
进位 + 与的结果 再除以2

这让我想起了数电课上的加法器
cao_julians 2012-03-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 cao_julians 的回复:]
解释似乎不对,简单测试一下:
x=0001,y=0111(二进制的)
(x+y)/2=(0001+0111)/2=1000/2=0100
((x&y)+(x^y))>>1=((0001&0111)+(0001^0111))>>1=(0001+0110)>>1=(0111)>>1=0011
[/Quote]
我看走眼了,括号位置不对
第二的测试应该是
(x&y)+((x^y)>>1)=(0001&0111)+((0001^0111)>>1)=0001+(0110>>1)=0001+0011=0100
解释应该是对的。

x&y的结果是同为"1”的位被保留(在+运算中是要产生向高位进位的),它不右移事实上就是除非后的进位了
而x^y的结果实际上保留0+1或者1+0的结果(异或也称为按位加--不要进位),再右移1位即除以2,
综合起来就是
前一段是进位,后一段是本位和除以2,相加即是平均值
面包大师 2012-03-04
  • 打赏
  • 举报
回复
LS括号看错了,引用楼上的测试
x=0001,y=0111(二进制的)
x&y = 0001
x^y = 0110 所以 (x^y)>>1 = 0011
所以
(x&y)+((x^y)>>1) = 0001 + 0011 = 0100
是正确的

cao_julians 2012-03-04
  • 打赏
  • 举报
回复
解释似乎不对,简单测试一下:
x=0001,y=0111(二进制的)
(x+y)/2=(0001+0111)/2=1000/2=0100
((x&y)+(x^y))>>1=((0001&0111)+(0001^0111))>>1=(0001+0110)>>1=(0111)>>1=0011
东莞某某某 2012-03-04
  • 打赏
  • 举报
回复
这个算法不用太计较,知道就行,我还以为是精妙的数学方法推出的
cao_julians 2012-03-04
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 guaner0203 的回复:]
可是这句话
X&Y是取相同的位与后的结果是X和Y相同位的一半
单拿出来怎么理解呢?
[/Quote]
那句话不严谨,只有1&1=1,推论是在这一位处1+1要产生进位。而0&0=0,和这个题目无关

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧