求两个数的平均数最常用的方法就是(a+b)/2,不过这种方法很容易溢出,原因是由于整形数据存储中,以补码形式存储,整型的取值范围为:
- unsigned int :0~2^32-1
- signed int : -2^31~2^31-1
所以当两个很大的数相加时就会溢出。
提出第二种方法:
printf("avg = %d\n", x+(y-x)/2);//分不同的部分
怎么理解呢?其实很简单,比如x有5块钱,y有10块钱,要想我们两个人的钱数相等,只需要将y比x多的一部分平分然后加上x与y共同拥有的部分。
但是实际上,这种方法还是会有缺陷,如果数据足够大的话,有溢出的可能性。
所以提出最后一种解决方法:
printf("avg = %d\n", (x&y)+(x^y)>>1);//xy相同部分取出来+(不同的部分)一分为二 不会溢出
这种方法与上面的方法理解是相同的,操作有所不同,这里采用的是位操作符,对比特位直接进行运算。
x&y 即是把x与y中相同的部分取出。
(x^y)是不同的部分取出,右移一位等价于/2.
这种情况不会溢出,原因是我们直接对比特位进行操作,并且也没有对比特位左移操作,所以不会溢出,相反我们对比特位进行右移数据只会越变越小。
综上所述:在求两数平均数时,推荐第三种解法更为稳妥。