操作符两道代码题
一 统计二进制中1的个数
方法一
我们来将这个问题幼儿园化一下
求出一个十进制数字的所有位数
是不是发现这个问题特别熟悉
是的 在我们以前的博客中遇到过
只需要不停的模10 除10就可以
那么在二进制当中
我们就只需要不停的模2除2就可以
求出每一位数之后可以再来判断每一位数是不是1
如果是1 count++
如果 不是 就看下一个数
int get_count1(int n)
{
int count = 0;
while (n)
{
if (n%2==1)
{
count++;
}
n =n / 2;
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = get_count1(n);
printf("%d\n",ret);
return 0;
}
代码如上
博主写这个代码的时候出现了一个小错误
n/2的值忘记赋值给n了 最终导致了进入死循环
大家写代码的时候一定要注意啊
这里我们可以计算出一个正数的2进制值
可是 如果是负数呢?
我们可以发现 运行结果如上
-1除以2确实是商0余负1啊
这样子代码就会出错了
那么有没有什么办法可以解决这个错误呢?
当然有 只需要当-1强制类型转换成无符号数就好了
代码如下
int get_count1(unsigned n)
如果说题目中规定死了 必须要输入一个int类型的参数 有没有办法解决呢?
当然也有
在函数内部重新定义一个参数强制类型转换就可以
参考代码如下
int get_count1(int n)
{
int count = 0;
unsigned m = (unsigned)n;
while (m)
{
if (m%2==1)
{
count++;
}
m =m / 2;
}
return count;
}
我们可以发现 代码可以完美运行
方法二
我们在上一节课学习了 位操作符
对于一个32位的数来说 我们只需要把它的每一位都拿出来
然后和1比较
比较个32次 就可以得到
难点就在于怎么将它的每一位取出来呢?
我们可以这样子 将它的&一个1
这样就能得到最后一个数字的值
然后我们再将这个数字右移一位 就可以拿到下一位数
之后继续比较 最终得到1有多少个
参考代码如下
int get_count1(int x)
{
int count = 0;
int i = 0;
for ( i = 0; i < 32; i++)
{
if ((x >> i) & 1 == 1)
count++;
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret =get_count1(n);
printf("%d\n", ret);
return 0;
}
然而这个代码有一个缺点
就是要计算32次才可以 那么 有没有一个更加简单的方法呢?
答案是有的
方法三
在二进制中 计算有多少个1可以使用这个公式
n&(n-1)之后将它的结果赋值给n
上面这一段代码执行多少次 就代表这个二进制数字n中有多少个1
这也是目前为止最完美的解法
代码如下
int get_count1(int x)
{
int count = 0;
while (x)
{
x = x & (x - 1);
count++;
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = get_count1(n);
printf("%d\n", ret);
return 0;
}
求二进制中不同位的个数
我们在上一篇博客中学习了^ 按位异或这个操作符
相同为0 不同为1
所以我们对这两个数使用^操作符 然后再统计其中1的个数 然后就可以完成求不同位的个数
我们统计1个数的解决方案以及再上面了
这里只需要套用一下就可以啦
int get_count1(int x)
{
int count = 0;
while (x)
{
x = x & (x - 1);
count++;
}
}
int main()
{
int n = 0;
int m = 0;
int x = 0;
scanf("%d %d", &n, &m);
x = m ^ n;
int ret = get_count1(x);
printf("%d\n", ret);
return 0;
}
运行结果如下图所示
以上就是本篇博客的全部内容啦 由于博主才疏学浅 所以难免会出现纰漏 希望大佬们看到错误之后能够
不吝赐教 在评论区或者私信指正 博主一定及时修正
那么大家下期再见咯