位运算小妙招-求二进制序列中0的个数

简介: 位运算小妙招-求二进制序列中0的个数

题目要求:

🚗求一个二进制序列中二进制位为0的个数

如:15 二进制序列0的个数为28


方法1:%2   /2

image.png

二进制:只有0和1 所以我们可以求出二进制1的序列之后,相减


int:4字节->32bit


二进制序列中0的个数 = 32 - 二进制序列1的个数


🛴%2 /2 判断条件不能写成 n%2 == 0 ->count++  然后返回count的值            因为偶数才符合n%2 == 0


🛵做法:求出二进制序列中1的个数之后,用32-去二进制序列1的个数得到的就是二进制序列中0的个数


size_t Binary_zero(size_t n)
{
    size_t count = 0;
    while (n)
    {
        if (n % 2 == 1)
        {
            count++;
        }
        n = n / 2;
    }
    return 32 - count;
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  size_t ret = Binary_zero(n);
  printf("%d\n", ret);
}
复制代码


🚎注意:当我们输入的是负数时,结果会出错,因为整数在内存中以补码形式存储,如果参数n定义为整形:负数时:会把补码->原码然后再参与下面的计算0的个数,这样就不符合要求!   所以我们可以把参数定义为无符号整数(size_t 即unsigned int),这样传参为负数时也不会出错!


🏍size_t :无符号整数,把内存中的补码当成原码看待

🚠打印16进制时也是把内存中的补码当成原码看待


方法2:得到每一位进行分别判断

image.png

🚇将二进制序列的每一个比特位分别判断

🚉**& :   0&1 = 0 1&1 = 1**

所以我们可以让二进制序列的每一位和1进行与运算,如果对于的二进制序列的位为1,那么结果就是1,反之则是0.


🚆右移(>>)得到每一位的二进制比特位之后,与1相与进行判断。使用计数器进行计数,如果相与的结果为1,计数器+1


右移:移动的是比特位.


size_t Binary_zero(int n)
{
  int i = 0;
  size_t count = 0;
  for (i = 0; i < 32; i++)
  {
    if ( ((n >> i) & 1) == 0)
    {
      count++;
    }
  }
  return count;
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  size_t ret = Binary_zero(n);
  printf("%d\n", ret);
}
复制代码

方法3-小妙招:x|(x+1)


✈x|(x+1)  : 把二进制序列中最低位的0变成1


可以用此方法统计二进制序列中0的个数,每使用一次,就把内存中的最低位的0变成1,最后为全1序列 ->补码为全1 ->对应十进制值为-1


🚋只要统计通过几次使用,值变成-1,就知道二进制序列有多少个0

所以判断条件为:🚀 while(n != -1)


size_t Binary_zero(int n)
{
  size_t count = 0;
  while (n != -1)
  {
    n = n | (n +1);
    count++;
  }
  return count;
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  size_t ret = Binary_zero(n);
  printf("%d\n", ret);
}
复制代码


相关文章
|
API Android开发 开发者
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
253 2
|
编解码 Java 编译器
【Protobuf】Protobuf中的Message语法规范
在Message中定义一个或者多个字段,FieldType是字段的数据类型,可以是基本类型(如int32、string、bool等)或其他定义的Message类型。fieldName是字段的名称,可以根据需求自定义。fieldNumber是字段的唯一标识号,用于在消息的二进制编码中标识字段。
775 0
|
人工智能 算法 决策智能
【五子棋实战】第2章 博弈树负值极大alpha-beta剪枝算法(一)
市面上比较常用的五子棋算法是博弈树极大极小值alpha-beta剪枝算法,该算法可以分成四个部分来讲解,它们是环环相扣的:博弈树 - 极大极小值搜索 - 负值极大法 - alpha&beta剪枝 。
834 0
|
SQL Java 数据库连接
成功解决:was not registered for synchronization because synchronization is not active
这篇文章是关于解决Mybatis在同步过程中出现"was not registered for synchronization because synchronization is not active"错误的技术博客。
成功解决:was not registered for synchronization because synchronization is not active
|
8月前
|
机器学习/深度学习 算法 数据可视化
利用SVM(支持向量机)分类算法对鸢尾花数据集进行分类
本文介绍了如何使用支持向量机(SVM)算法对鸢尾花数据集进行分类。作者通过Python的sklearn库加载数据,并利用pandas、matplotlib等工具进行数据分析和可视化。
638 70
|
10月前
|
机器学习/深度学习 数据采集 搜索推荐
利用Python和机器学习构建电影推荐系统
利用Python和机器学习构建电影推荐系统
423 1
|
缓存 算法 编译器
C/C++编译器内存优化技术:内存优化关注程序对内存的访问和使用,以提高内存访问速度和减少内存占用。
C/C++编译器内存优化技术:内存优化关注程序对内存的访问和使用,以提高内存访问速度和减少内存占用。
496 0
|
设计模式 算法 中间件
【C/C++ CommonAPI入门篇】深入浅出:CommonAPI Core与CommonAPI DBus的协同工作原理
【C/C++ CommonAPI入门篇】深入浅出:CommonAPI Core与CommonAPI DBus的协同工作原理
684 0
|
安全 编译器 API
C++系统日志库精选:深入剖析glog与log4cplus,轻松搭建高效日志系统
C++系统日志库精选:深入剖析glog与log4cplus,轻松搭建高效日志系统
1924 0
|
Docker 容器
docker 设置国内镜像源
docker 设置国内镜像源
85305 1