一 统计二进制中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; }
运行结果如下图所示
以上就是本篇博客的全部内容啦 由于博主才疏学浅 所以难免会出现纰漏 希望大佬们看到错误之后能够
不吝赐教 在评论区或者私信指正 博主一定及时修正
那么大家下期再见咯