位运算n=(n-1)快速统计二进制1的个数
看到一篇博客,发现n&=(n-1)竟然能够快速统计二进制1的个数,经过博主同意特此拿来分享一下。
首先,分析一下该式子,先可以简化为
n=n&(n-1);
我们先做一个实例,
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
十进制 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
二进制 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 |
我们先试着求7中二进制1的个数k
0111
& 0110
-------------
0110(6)
然后对其结果继续进行上述操作
0110
& 0101
-------------
0100(4)
继续上述操作
0100
& 0011
-------------
0000
结束操作。
至此,我们可以发现,每次&操作后,0111(7)的二进制数中最右边的1都被消除1个,
第一次&操作后,结果为0110
第二次&操作后,结果为0100
第三次&操作后,结果为0000
而k恰好与&操作的次数是相同的。那么我们可以猜测这两者必然存在直接关联关系。
不过,当二进制数中1的位置不连续,中间有若干个0这个公式也能“跳过”0,直接统计1的个数吗?
下面我们在举个实例37(0010 0101)这个比较有代表性
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
十进制 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
二进制 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 |
同样进行&操作,
100101
& 100100(36)
----------------------
100100(36)
继续重复上述操作
100100
& 100011
--------------------
100000(32)
继续重复上述操作
100000
& 011111
--------------------
000000
结束。
到这里,我们会得出一个结论,
1的位置无非就三种情况,头和中间、尾部
a.在尾部的情况
当末尾是1的时候(奇数),与前一个数(偶数)进行&操作后,结果必为0,末尾的1消除
b.在头部的情况
当1只在头部的时候,其余位上都为0.类似8(1000),4(0100),与前一个数(全1,7(0111),3(0011))进行&操作时,结果必为0.
c.在中间的情况
无非也是上述两种情况的递归。保证末尾位为0,因为之前已经处理过尾部的情况了。
比如,尾部是*0010结尾,*0100结尾,*1010结尾,*11010结尾。他们对应的前一个数分别是:*0001,*0011,*1001,*11001。(*代表左边还有若干个0和1)
0010
& 0001
-------------
0000
结束。
0100
& 0011
-------------
0000
结束。
1010
& 1001
--------------
1000(消除最右边的1,下一步进行第二种情况的处理)
结束。
11010
& 11001
---------------
11000(消除最右边的1,下一步进行第一种情况的处理)
结束。
--------------------------------分割线-------------------------------------
到这里,我们就可以看出,每次在最右的1设置一个flag的话,
当它(i)与它前一位(i-1)进行&操作时,对flag左边的1是没有影响的,每次得到的结果,就会将flag位置及右边所有的数置为0.
例如:11010&11001 ==11000(24)
那么,结束条件是什么呢?
那就是当&操作后的结果为0,循环结束。
好啦,分析就到这里。下面附上源代码供看官们欣赏哈~
- for (int count =0; n; ++count)
- {
- n &= (n -1) ; //每次消除最右边的1,当n为0结束
- }
另一种写法:
- count=0
- while(k){
- k=k&(k-1);
- count++;
- }
位运算n=(n-1)快速统计二进制1的个数相关推荐
- Excel如何快速统计各字体颜色个数
今天老板又扔给小王一份文件,让他去统计各字体颜色的单元格个数,字体颜色很相似.小王一个轻度色盲如何在一分钟内统计出来呢?下面就跟大家分享一下. 1.如下图,是老板扔给小王的文件,老板让他按字体颜色统计 ...
- python语言中1010的二进制表示_Python语言中的按位运算
(转)位操作是程序设计中对位模式或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常与加 ...
- java 二进制位运算_Java中的二进制与位运算
大家在阅读一些算法或者一些开源框架的时候,总会见到~,>>,>>>,|这种大量的位运算,因此想要读明白 这部分代码,对于计算机的二进制操作以及位运算是必须要了解的,那么本 ...
- python二进制移位_python学习特辑——二进制和位运算篇
以前学习java的时候,二进制和位运算只停留在"懂"的程度,从来没有花时间去推导和总结,作为一个数学系的学生,一直想花点时间做推理证明 java和python关于二进制和位运算的规 ...
- 算法笔记(一)位运算、二分、基本递归、排序、基本数据结构
文章目录 位运算 原码.补码与反码 左移右移`<<` & `>>` 无符号右移 异或运算`^` 位运算常用技巧 取相反数 反转0-1 判断负数与非负数 数组交换两元素位 ...
- java中位运算详解
位运算 什么是位操作? 程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算就是直接对整数在内存中的二进制位进行操作.比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算 ...
- java 位运算_java学习之运算符与表达式(四)
(6)位运算符 位运算是指对整数按二进制的位进行运算. 位运算用于整数或字符类型. 有7个:~(非).&(与).|(或).^(异或).<>(右移).>>>(无符号 ...
- C语言学习笔记--位运算
这一节主要说的是位运算,计算机中的执行速度:位运算 > 加减 > 乘除 > 求余 位运算就是将数字转换成二进制后进行运算,之后再将数字转换成原来的进制 与运算:当两个数相与时,只有都 ...
- c语言位运算+乘法,关于c语言中的位运算。。。
标签:c++ 位运算是一种针对二进制数的一种运算 位运算 共有六种 都有其对应得操作符号 & (and) 位于 | (or) 位或 ~ ...
最新文章
- wpf treeView,避免横向滚动条自动偏移。 ContentHorizontalOffset
- 两个service事务统一_拜托,别再让我优化大事务了,我的头都裂了
- MSSQL中实现多表更新
- PL/SQL 存储过程
- STM32学习之TFTLCD
- Spring Security 11 种过滤器介绍
- 数据库实验四 视图实验
- [转]中国象棋谚语大全
- ActiveMQ在win7下启动失败解决方案
- Codewars 刷题笔记(Python)6.Multiples of 3 or 5
- Double计算精度丢失(金融入门知识点)
- vue项目兼容IE浏览器,判断IE11以下,则提示浏览器版本过低,更新浏览器页面
- ios设置中性黑体_iOS - 使用自定义字体-苹方字体
- Spark配置参数中英文对照
- 传统CD车机面板操作说明
- 宇视NVR 宇视录像机RTSP规则接入LiveNVR实现Web H5无插件直播和录像
- 不知名菜鸟的day15
- Node.js+Express+Vue+MySQL+axios的项目搭建
- 躲过了大跌也会失去大涨
- 线路中央计算机系统(LCC)的功能有哪些,AFC系统介绍PPT主题课件.ppt