文章目录

  • 问题引入
  • 思路一
    • 图解
    • 弊端
  • 思路二
    • 完善
  • 思路三
  • 拓展
    • 思路
    • 进一步优化

问题引入

题目:求一个数字的二进制位中有多少个1

假设我们给定一个数字为7,7的二进制为0000 0111(已省略前面的24个0)接下来我们来探究一下如何求出7的二进制当中有多少个数字1

思路一

要想求出一个数字有多少个1,我首先会想到,要是能求出这个数字的每一位数字,那么不就直接知道有多少个1了,接下来的问题就是,如何求出这个数字的每一位呢?

我们知道0 & (0/1)结果都是0,只有当1&1时结果才为1,而二进制中无非就是0和1 ,所以一个数的二进制的最后一位就可以通过&1得出来

图解

知道了一个数二进制的最后一位之后,只每次需要将这个数进行右移1位,一共右移32次,每次&1的结果为1,计数器就+1,即可统计出这个数字一共有多少个数字1

代码如下:

public static int Findnum(int n) {int count = 0;for (int i = 0; i < 32; i++) {if (((n>>i)&1)==1) {count++;}}return count;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(Findnum(n));}

弊端

这样子确实可以计算出一个数字的二进制的1的个数,但是7这个数字的二进制除去后面3位是1,其余都是0,也就是说在向右移位3次之后,后面就全是0了,所以之后的29次循环就是在做无用功了,所以执行效率很低

思路二

在每进入一次循环后,就将移向右移动一位的n后的n重新赋值给n,再判断n是否为为0,要是为0,就说明此时的n的二进制全是0,就可以直接返回count,这样就可以有效的不必要的减少循环次数

public static int Findnum(int n) {int count = 0;while (n != 0) {if ((n& 1) == 1) {count++;}n = n >> 1;}return count;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(Findnum(n));}

完善

但是,要是输入的数字为负数会怎么样呢?假设输入一个-1,每右移一位数字,在二进制的左端还是会补一个符号位1,所以代码就会死循环

其实只要改成无符号右移,就会在二进制的左端补0,这样就可以解决负数的问题

public static int Findnum(int n) {int count = 0;while (n != 0) {if ((n& 1) == 1) {count++;}n = n >>> 1;}return count;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(Findnum(n));}

思路三

但是,还能不能再优化一下?上面的代码还是在一位一位按顺序进行移位,有没有更好的方法可以将1的个数全部快速的求出来?

其实,还是有的,要是将n每次&(n-1),那么每次就会有一个1被消去,计数器统计一下即可

这样子每次消去一个1,效率也会增加

public static int Findnum(int n) {int count = 0;while (n != 0) {n = n & (n - 1);count++;}return count;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(Findnum(n));}

拓展

给出一个数,判断它是不是2的次方

要判断是不是2的次方,就要知道2的次方的数是什么样子的

0000 0010

0000 0100

0000 1000

思路

可以看出2的次方数的二进制都只有一个1,那么就可以直接按照第一种方法在32位中统计所有的1的个数,要是个数为1,就是2的次方数,就返回1,1的个数不是1,就返回-1

 public static int multipleOfTwo(int n) {int count = 0;for (int i = 0; i < 32; i++) {if (((n>>i)&1)==1) {count++;}}if (count == 1) {return 1;} else {return -1;}
public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(multipleOfTwo(n));}

但是,还是要右移32次才能知道最终count的结果,所以效率还是不高

进一步优化

但要是借用方法三的思路,将n&(n-1),要是n是2的次方数,&(n-1)结果就一定会是0

  public static int multipleOfTwo(int n) {if ((n & (n - 1)) == 0) {return 1;}elsereturn -1;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(multipleOfTwo(n));}

感谢大家的阅读,如有错误,还请大家指正。

你确定会了比特位计算?相关推荐

  1. 《LeetCode力扣练习》第338题 比特位计数 Java

    <LeetCode力扣练习>第338题 比特位计数 Java 一.资源 题目: 给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ...

  2. CAN 总线 之六 BOSCH CAN 比特位填充(编码规则)、归零编码(RZ)和不归零编码(NRZ)

    帧格式   在 CAN 总线中,为了确保足够的转换以保持同步,在相同极性的 5 个连续位之后使用位填充.下面以 标准格式来进行说明,先看下面标准格式的帧的图示: 在某些文档中,将 CAN 帧分为以下部 ...

  3. Intel 64/x86_64/IA-32/x86处理器 - 通用指令(4) - 比特位设置指令/字节设置指令

    Bit and Byte Instructions 比特指令测试并修改操作数的某些比特位:字节指令设置字节操作数的值,用来指示EFLAGS标志寄存器的状态. 指令 描述 BT 测试比特位(将要测试的比 ...

  4. LeetCode每日一题:比特位计数(No.338)

    题目:比特位计数 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回. 复制代码 示例: 输入: 2 输出: [0,1, ...

  5. Leetcode338. 比特位计数

    Leetcode338. 比特位计数 题目: 给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans ...

  6. 比特位计数--C++ bitset 用法

    比特位计数 前言 一.示例 二.代码解析 1.比特位计数 2.测试代码 3.结果 三.C++ bitset 用法 1.构造函数 2.一些函数 3.结果 总结 前言 给定一个非负整数 num.对于 0 ...

  7. (LeetCode C++)比特位计数

    给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案. 示例 1: 输入:n = 2 输 ...

  8. 反转比特位(文章最后有干货)【转】

    转自:https://blog.csdn.net/wuxianglonghaohao/article/details/21602305 http://www.newhottopic.com/2014/ ...

  9. Rowhammer漏洞致“比特位翻转”,如何解决?

    读者们也许会觉得Rowhammer和比特位翻转是音乐及舞蹈行业的专业术语,但其实他们指的是存在于动态随机访问存储(DRAM)--大多数电子设备中都存在的一种核心组件中的某种非常严重的漏洞.随着驱动器中 ...

最新文章

  1. 【面试现场】如何在10亿数中找出前1000大的数
  2. hdu 4468 spy 极其精彩的一道kmp灵活运用题
  3. linux常用命令--diff
  4. c++中algorithm头文件、STL库简介及使用说明
  5. Codeforces 864E Fire(背包DP)
  6. 一般二叉树的顺序存储Java_100-顺序存储二叉树思路图解
  7. C/S架构网络聊天软件——Java Chat Application 用java做一个聊天机器人
  8. 12、设计模式-结构型模式-外观模式
  9. 设计模式---工厂方法模式(c++实现)
  10. UNIX环境高级编程习题——第一章
  11. MTK驱动移植相关路径
  12. py文件编译成pyc文件
  13. 计算机网络Flash教学课件,flash动画教学课件
  14. adams功能区不显示_Word 空白的页面显示与隐藏,与五种试图的简介操作技巧
  15. C#——NPOI对Excel的操作、导入导出时异常处理(三)
  16. 两个方法做APP界面展示图片
  17. DDR5内存条容量计算
  18. 洛谷P2744 [USACO5.3]量取牛奶Milk Measuring
  19. 用Python做一个好玩的朋友圈九宫格抽奖
  20. 用Echarts绘制折线图-----阶梯图

热门文章

  1. opencv幻灯片代码
  2. 项目oracle优化记录
  3. Go-defer,panic,recover
  4. 电视机一直显示android正在升级,L版本开机提示“Android正在升级或启动”
  5. 云计算基础与应用 第四章 云网络
  6. 焦盈鑫老师:认知突围是一个人立于不败之地的根本
  7. 安卓动画入门_网络动画入门
  8. 刘强东翻脸!忍不住向兄弟们下手,真相令人震撼!
  9. nextTick 使用场景
  10. 感叹珊瑚虫QQ的离去