求证

supernove 2010-12-24 09:48:26
求证
pop(x) = x -[x/2]-[x/4]-...-[x/2^31]

pop(x)为数x二进制表示中 1 的个数(32位)

摘自《代码之美》
...全文
91 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
prohibit 2010-12-25
  • 打赏
  • 举报
回复
比如一个int类型数13占4个字节、用完整的32位二进制数表示是0000...00001101、即1101前面一共有28个0;
x/2、x/4、...、x/2^31可看成是依次往右移1、2、...、31位,也就是x/2相当于x>>1、x/4相当于x>>2……
所以这里可以这样处理:若x移位(1-31位)前是偶数、即二进制的最低位为0,且a=x/2等于b=x-x/2,若x移位(1-31位)前是奇数、即二进制的最低位为1,且1加a=x/2等于b=x-x/2,这里的思路就是判断移位前最低位是0(b-a==0)还是1(b-a==1)、然后计算是1的次数;
好,下面以刚才说的13(二进制为1101)为例,以另一个变量count=0来计数1的个数:
往右移1位得110(x>>1,a=x/2=6)、移除最低位1,b=x-x/2=7,count += ((x-x/2)-x/2);
往右移2位得11(x>>2,a=x/4=3)、移除最低位0,b=x/2-x/4=3,count += ((x/2-x/4)-x/4);
往右移3位得1(x>>3,a=x/8=1)、移除最低位1,b=x/4-x/8=2,count += ((x/4-x/8)-x/8);
往右移4位得0(x>>4,a=x/16=0)、移除最低位1,b=x/8-x/16=1,count += ((x/8-x/16)-x/16);
往右移5位得0(x>>5,a=x/32=0)、移除最低位0,b=x/16-x/32=0,count += ((x/16-x/32)-x/32);
...
往右移30位得0(x>>30,a=x/2^30=0)、移除最低位0,b=x/2^29-x/2^30=0,count += ((x/2^29-x/2^30)-x/2^30);
往右移31位得0(x>>31,a=x/2^31=0)、移除最低位0,b=x/2^30-x/2^31=0,count += ((x/2^30-x/2^31)-x/2^31);
剩下二进制最后一位x/2^31,要么为1要么为0,count += x/2^31

count = ((x-x/2)-x/2) + ((x/2-x/4)-x/4) + ((x/4-x/8)-x/8) + ((x/8-x/16)-x/16) + ((x/16-x/32)-x/32) + ... + ((x/2^29-x/2^30)-x/2^30) + ((x/2^30-x/2^31)-x/2^31) + x/2^31 = x-x/2-x/2 + x/2-x/4-x/4 + x/4-x/8-x/8 + x/8-x/16-x/16 + x/16-x/32-x/32 + ... + x/2^29-x/2^30-x/2^30 + x/2^30-x/2^31-x/2^31 + x/2^31 = x - x/2 - x/4 - x/8 - x/16 - x/32 - ... - x/2^30 - x/2^31
得证~~
supernove 2010-12-25
  • 打赏
  • 举报
回复
这两种思路我知道,我主要还是想弄清楚,这个式子的理论上的意义
还是多谢
prohibit 2010-12-24
  • 打赏
  • 举报
回复
理论上的证明不会,就写这段代码来证明
#include <iostream>
using namespace std;

int pop(int x)//《代码之美》思路
{
int ret = x, tmp = 1;
for(int i = 1; i <= 31; i++)
{
tmp *= 2;
ret -= (x/tmp);
}
return ret;
}
int jud(int x)//另一种思路、将结果与上一种思路对比
{
int ret = 0, tmp = x;
while(tmp)
{
if(tmp & 0x01)
ret++;
tmp = tmp >> 1;
}
return ret;
}
int main(void)
{
int n = 1225;//n值可以改变
char arr[32] = {0};

itoa(n, arr, 2);//二进制字符串
puts(arr);

cout << "pop() = " << pop(n) << endl;
cout << "jud() = " << jud(n) << endl;

system("pause");
return 0;
}

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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