C++ 书上说 (x&y)+((x^y)>>1)的功能是取两个数的平均值,哪位大侠可以帮我解释下啊?

如题所述

很牛X的一个思路,虽然不算高效,但如果在汇编中的话,这种方法可以不产生高位溢出。
我琢磨了一下,大概思路应该是这样:

(x&y)+((x^y)>>1),把x和y里对应的每一位(指二进制位)都分成三类,每一类分别计算平均值,最后汇总。其中,一类是x,y对应位都是1,用x&y计算其平均值;一类是x,y中对应位有且只有一位是1,用(x^y)>>1计算其平均值;还有一另是x,y中对应位均为0,无须计算。

下面我再分别说明一下前两种情况是怎样计算的:

x,y对应位均为1,相加后再除以2还是原来的数,如两个00001111相加后除以2仍得00001111,这是第一部分。
第二部分,对应位有且只有一位为1,用“异或”运算提取出来,然后>>1(右移一位,相当于除以2),即到到第二部分的平均值。
第三部分,对应位均为零,因为相加后再除以二还是0,所以不用计算。
三部分汇总之后就是(x&y)+((x^y)>>1)

顺便解释一下前面说到可以避免溢出。
假设x,y均为unsigned char型数据(0~255,占用一字节),显然,x,y的平均数也在0~255之间,但如果直接x+y可能会使结果大于255,这就产生溢出,虽然最终结果在255之内,但过程中需要额外处理溢出的那一位,在汇编中就需要考虑这种高位溢出的情况,如果(x&y)+((x^y)>>1)计算则不会。
温馨提示:内容为网友见解,仅供参考
第1个回答  2018-04-18

(x&y)+((x^y)>>1),把x和y里对应的每一位(指二进制位)都分成三类,每一类分别计算平均值,最后汇总。其中,一类是x,y对应位都是1,用x&y计算其平均值;一类是x,y中对应位有且只有一位是1,用(x^y)>>1计算其平均值;还有一另是x,y中对应位均为0,无须计算。

下面我再分别说明一下前两种情况是怎样计算的:
1)、x,y对应位均为1,相加后再除以2还是原来的数,如两个00001111相加后除以2仍得00001111,这是第一部分。
第二部分,对应位有且只有一位为1,用“异或”运算提取出来,然后>>1(右移一位,相当于除以2),即到到第二部分的平均值。
第三部分,对应位均为零,因为相加后再除以二还是0,所以不用计算。
三部分汇总之后就是(x&y)+((x^y)>>1)

本回答被网友采纳
第2个回答  2011-08-24
相当于|x+y|+|x-y|/2,
第3个回答  2011-08-24
太巧妙了。

C++ 书上说 (x&y)+((x^y)>>1)的功能是取两个数的平均值,哪位大侠可以帮...
(x&y)+((x^y)>>1),把x和y里对应的每一位(指二进制位)都分成三类,每一类分别计算平均值,最后汇总。其中,一类是x,y对应位都是1,用x&y计算其平均值;一类是x,y中对应位有且只有一位是1,用(x^y)>>1计算其平均值;还有一另是x,y中对应位均为0,无须计算。下面我再分别说明一...

C语言中,(x&&y)==(x||z)的意思是?值为?
x和y都为非零值时,(x && y)为真(1),任意一个为零,或都为零时,(x && y)为假(0),&&为逻辑与操作符。x和z有一个为真(非零)时,或都为真时,(x || z)为真(1),只有x和z都为零时,(x || z)才为假(0),||为逻辑或操作符。==是比较操作符,如果两边都为真或都为假,...

c++ for循环 输入两个整数X和Y,输出两者之间的素数个数(包括X和Y)。
y,data,ans=0; cin>>x>>y; if(x > y){ int temp=x; x=y; y=temp;} for(int i =x;i<=y;i++) { int data=i; bool flag = true; for(int j=2;j<=sqrt(data);j++) \/\/这里修改成平方根更好,如果你...

用C++编写 从键盘输入两个整数,分别输出这两个数的和、差、积、商以及...
int x,y;char c;while(cin>>x>>y>>c){ getchar();switch(c){ case '+':cout<<x+y<<endl;break;case '-':cout<<x-y<<endl;break;case '*':cout<<x*y<<endl;break;case '\/';if(y==0)cout<<"无解!"<<endl;else cout<<x\/y<<endl;break;case '%':if(y==0)cout...

如何在c++定义一个学生类以实现平均成绩的计算和查询功能?
毕晓鹏认为,自动驾驶中间件最主要的作用是:对下,它能够去适配不同的OS内核和架构;对上,它能够提供一个统一的标准接口,负责各类应用软件模块之间的通信以及对底层系统资源的调度。据毕晓鹏解释,前者,使开发者们无需考虑底层的OS内核是什么,也无需考虑硬件环境是什么,即不仅实现了应用软件与OS的解耦,也实现了应用...

在c++编程中,这两个句子,n=--x&&++y和n=(--x)||(++y)是什么意思?特别是...
如a>0且b>9写成a>0&&b>9;同理||是或;即a>0或b>9表达为a>0||b>9,需要&&两边为真(即非0)结果才为真,||只要有一边为真(即非0)结果就为真,应注意||和&&都是先判断左再到右的,n=(--x)||(++y)中,先做的是--x;即x自减1后若结果为假(等于0),就会再执行++y;...

C语言取余的原理是怎么回事? 比如 int X,Y X-X\/Y*Y=x%y
如果N是奇数,那么X^N = X*X^(N-1) = X *(X*X)^[N\/2]; 其中[N]是指小于或等于N的最大整数。 C++实现功能函数: \/* 函数功能:利用模运算规则,采用递归方式,计算X^N(% P) 函数名:PowerMod 输入值:unsigned int x,底数x unsigned int n,指数n unsigned int p,模p 返回值:unsigned int,X^N...

X&Y是取相同的位与。为什么与后的结果是X和Y相同位的一半?
你是看程序员面试宝典里面的题目吧,我也在看,发现这地方有问题。貌似只有当x和y同为奇数或偶数时书上才是正确的;至于x&y的结果是x和y相同位的一半这种说法我也不理解,或许只是作者自己想的,不一定正确。

C语言,谁能解释一下这串代码的意思
函数体→int z = (x * y); return z; ↑返回语句 } 图1.5函数的构成部分使用函数前,要先进行声明。函数声明或原型(prototype)告诉编译器函数所取的参数个数、每个参数的数据类型和函数返回值的数据类型。清单1.4列示了这个概念。新术语 原型(prototype)是函数外观的声明或其定义的说明。清单1....

在c语言中括号中有两个数如;(x,y)在没有特定说明的情况下去那个值...
不是很明白你的意思。()也是一种运算符。就像数学里面的()是一个道理。比如:3*(1+2);就是一样道理。(3,5)是没有意义的。在有宏定义或函数的情况下才有意义。比如:define sum(x,y) ( x+y)程序中仅仅进行x,y的简单替换。如果硬要对(x,y)取值,那么应该去y的值。

相似回答