求二进制中的1/0的个数

求二进制中1的个数 阅读详情

设x为二进制数1111 1111 1111 1010,则求x中0的个数操作:

int countofZero(int x)
{
    int N = 0;
    while (x + 1)
    {
        N++;
        x |= (x + 1);
    }
    return N;
}

求x中1的个数操作:

int countOfOne(x)
{
    int N = 0;
    while(x)
    {
        N++;
        x &= (x - 1); 
    }
    return N;
}

昨天刷题的时候刷到MIT HAKMEM算法,用于求整型数中的'1'的个数,阅读了几篇文章,在这里整理一下:

(参考(侵删):https://blog.youkuaiyun.com/msquare/article/details/4536388)

算法如下:

int bitcount(unsigned int n)  
{  
    unsigned int tmp;  

    tmp = n  
        - ((n >> 1) & 033333333333)  
        - ((n >> 2) & 011111111111);  

    tmp = (tmp + (tmp >> 3)) & 030707070707;  

    return (tmp%63);  
}  

分析:

1. 整型数 i 的数值,实际上就是各位乘以权重——也就是一个以2为底的多项式:

i = A0*2^0+A1*2^1+A2*2^2+... 因此,要求1的位数,实际上只要将各位消权:

i = A0+A1+A2+...所得的系数和就是'1'的个数。

2. 对任何自然数n的N次幂,用n-1取模得数为1。

3. 因此,对一个系数为{Ai}的以n为底的多项式P(N), P(N)%(n-1) = (sum({Ai})) % (n-1) 。

4. 将32位二进制数的每6位作为一个单位,看作以64(2^6)为底的多项式:

i = t0*64^0 + t1*64^1 + t2*64^2 + t3*64^3 + ...

各项的系数ti就是每6位2进制数的值。

这样,只要通过运算,将各个单位中的6位数变为这6位中含有的'1'的个数,再用63取模,就可以得到所求的总的'1'的个数。

5. 取其中任意一项的6位数ti进行考虑,最简单的方法显然是对每次对1位进行mask然后相加,即

(ti>>5)&(000001) + (ti&>>4)(000001) + (ti>>3)&(000001) + (ti>>2)&(000001) + (ti>>1)&(000001) + ti&(000001)

int bitcount(unsigned int n)  
{  
    unsigned int tmp;  
  
    tmp = (n &010101010101)  
     +((n>>1)&010101010101)  
     +((n>>2)&010101010101)  
     +((n>>3)&010101010101)  
     +((n>>4)&010101010101)  
     +((n>>5)&010101010101);  
  
    return (tmp%63);  
}  

第一步优化:

6位数中最多只有6个'1',也就是000110,只需要3位有效位。上面的式子实际上是以1位为单位提取出'1'的个数再相加求和求出6位中'1'的总个数的,所以用的是&(000001)。如果以3位为单位算出'1'的个数再进行相加的话,那么就完全可以先加后MASK。算法如下:

tmp = (ti>>2)&(001001) + (ti>>1)&(001001) + ti&(001001)

(tmp + tmp>>3)&(000111)

int bitcount(unsigned int n)  
{  
    unsigned int tmp;  
  
    tmp = (n &011111111111)  
     +((n>>1)&011111111111)  
     +((n>>2)&011111111111);  
       
    tmp = (tmp + (tmp>>3)) &030707070707;  
  
    return (tmp%63);  
}  

注:代码中是使用8进制数进行MASK的,11位8进制数为33位2进制数,多出一位,因此第一位八进制数会把最高位舍去(7->3)以免超出int长度。

从第一个版本到第二个实际上是一个“提取公因式”的过程。用1组+, >>, &运算代替了3组。并且已经提取了"最大公因式"。

第二步优化:

又减少了一组+, >>, &运算。被优化的是3位2进制数“组”内的计算。再回到多项式,一个3位2进制数是4a+2b+c,我们想要求的是a
+b+c,n>>1的结果是2a+b,n>>2的结果是a。

于是: (4a+2b+c) - (2a+b) - (a) = a + b + c

中间的MASK是为了屏蔽"组间""串扰",即屏蔽掉从左边组的低位移动过来的数。

 

以上,这个算法分析我还没有看得太懂,先标记一下,下次再看~~~

华为/H3C/锐捷交换机配置命令对比表:一张图搞定VLAN划分与端口设置 本文详细对比了华为、H3C、锐捷三大品牌交换机在VLAN划分与端口设置中的配置命令差异,提供从基础配置到高级功能的横向对比表,帮助网络工程师快速掌握多品牌设备混用环境下的配置技巧,提升工作效率。 阅读详情

相关推荐

qt5.14.2+vs2019配置msvc2017编译器

qt5.14.2+vs2019配置msvc2017编译器 在使用qt编译程序时此前一直使用的是自带的MinGW 32-bit和64-bit,现在想使用msvc编译器。本次使用的是qt5.14.2,vs2019,需要配置msvc2017的32-bit和64-bit编译器。 1、首先安装好qt5.14.2和vs2019,其次在visual studio installer选择修改,然后选择msvc2017对应的组件,本次安装的是这两个 2、打开qt creator的工具–选项–kits–编译器,选择Manu

bangtanhui的博客 1万+

【002 位操作】如何求解二进制中0的个数

对于输入的数,我们可以直接,不需要我们对数字做额外处理。只需要直接对数字进行0个数的判定。

kashine的博客 1691

因果推断综述-A Survey on Causal Inference

最近读到一篇讲述很全面的综述文献-《A Survey on Causal Inference》,对于接触因果推断不久的同学而言是特别详细的介绍和科普。文献很长,我会分成几部分介绍。 目录 摘要 第一部分:简介 第二部分:因果推断基础知识 第三部分:基于三种假设的因果推断方法 第四部分:实验 第五部分:应用 摘要 几十年来,因果推理是一个跨许多领域的关键研究主题,如统计、计算机科学、教育、公共政策和经济学。与随机对照试验相比,研究方向由于可用数据量大且预算要求低,如今,从观测数据..

海边凝望的博客 3182

华为机试题-判断二进制中0的个数【4】

题目描述: 输入一个10进制数字,请计算该数字对应二进制中0的个数,注意左数第一个1之前的所有0都不需要计算。不需要考虑负数的情况。 我之前的博客讲过类似的问题,博客地址如下: http://blog.youkuaiyun.com/lpjishu/article/details/51323722 思路分析: 首先要注意不是统计所有的0,而是统计第一个1之后的0 要使用位运算,如何判断什么时候...

238

从登录到应用可见:在 SAP S/4HANA Cloud Private Edition 中创建用户与打通 SAP Fiori 权限的完整思路

在SAP S/4HANA系统中,用户创建远非简单的账号开通,而是涉及认证、授权、数据访问等多维度的复杂过程。用户主数据记录(User Master Record)是系统访问的起点,包含登录方式、角色分配等关键信息。认证解决"你是谁"的问题,授权则决定"你能做什么"。SAP Fiori访问链路涉及Launchpad内容分配、应用启动映射、OData服务权限等多层校验。角色(Role)通过PFCG维护,包含业务目录(Catalog)和空间(Space)等元素,共同构成完整

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 148

40、5G NR射频要求解析

本文详细解析了5G NR射频相关要求,包括参考灵敏度与动态范围的定义、接收机对干扰信号的抗扰性要求(如阻塞、邻道选择性等)、辐射射频要求在FR1和FR2频段的差异,以及多标准无线电基站(MSR)的发展及其对射频要求的影响。内容涵盖测试模型、干扰场景、具体指标和实现挑战,为理解和应用5G NR射频规范提供了全面指导。

qsc901234的博客 245

二进制中0的个数

师兄的一道网易面试题问题:求二进制0的个数,要求从第一位为1往后统计个数答:主要考虑正负数情况。对于正数,在不为0的情况下,计算其2进制,容易得0的个数。对于负数,因为已知第一位是1的,所以不用担心有高位0,直接取1,然后依次左移,看&原值是不是0。停止条件是这个数为0。public static int numberOf0(int num){ int count=0; i...

擦肩的阳光的专栏 5114

华为od 面试八股文_前端_02_含答案

华为od 面试八股文_前端_02_含答案

MISAYAONE的博客 1998

二进制0和1的个数,2的次幂

目录 1、二进制中0的个数 2、二进制中1的个数 3、一个数是不是2的几次幂 1、二进制中0的个数 使用|运算:有一个是1则为1,x|(x+1)可以将数字二进制位的最低位的0改为1,逐渐递进,直到将二进制位改为全1,对应原码-1结束。 #include<stdio.h> int main() { char x =5, count = 0; while (x+1)//当x=-1的时候退出循环 { count++; x =x|(x + 1); } printf("%d

m0_58342797的博客 503

LearningToRank(LTR)排序算法LGBMRanker的原理和使用

1. 写在前面 在最近新闻推荐的比赛中, 接触到了一个排序模型LGBMRanker, 该模型与普通的分类模型LGBMClassifier不太一样, 普通的分类模型在进行推荐的时候, 往往是先预测某个商品或者文章用户会不会点击, 也就是它的目标是预测用户点击某篇文章或者某个商品的概率, 然后根据这个概率值进行排序, 排完之后,把最靠前的几个返回回来给用户进行推荐。 而LGBRanker模型, 它不关心用户点击某篇文章的概率, 而是根据用户点击或者不点击的这个行为, 直接去预测最后商品或者文章的一个相对顺序,

Miracle8070 1万+

OCR文字识别基础

ocr文字识别

m0_47405013的博客 1755

二进制中 0的个数

题目:输入一个整数,输出该数二进制表示中0的个数。其中负数用补码表示。 思路:二进制与1求&,即判断二进制最后一位是否为1,若为1,则跳过,否则计数器+1;然后整数右移一位,直到整数为0。 这个思路还是挺好理解的,就是二进制依次右移,查看最后一位是否为0,是就+1,不然就跳过。 int count_1_num = 0; while(num != 0) { if((num&...

qq_36167072的博客 1432

YOLOv11改进有效系列目录 - 包含卷积、主干、检测头、注意力机制、Neck上百种创新机制 - 针对多尺度、小目标、遮挡、恶劣天气等问题

在一些特定情况下,目标检测任务由于多种因素的影响,变得更加复杂和困难。以下是几类常见的困难目标检测场景:1. 小目标检测定义:小目标检测是指当目标在图像中的占比非常小时,模型需要准确识别和定位这些目标。典型场景包括远程监控、卫星图像分析等。挑战1. 低分辨率:由于目标在图像中占据像素较少,细节缺失,特征提取难度增加。2. 特征不足:小目标缺乏明显的形状和纹理特征,容易被复杂背景淹没。3. 检测难度大:由于小目标与背景之间的对比度较低,误检的几率上升。4. 数据不平衡。

qq_64693987的博客 4万+

【C语言】三种方法求二进制中1的个数

输出一个整数的32位二进制中1的个数

weixin_67711401的博客 4240

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

求二进制中1的个数。(三种方法)

求二进制中1的个数。(三种方法) 第三种最高效!!!

wihkum 1万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【C语言】求二进制中1的个数(三种方法)

该方法也是与其他两种方法拉开水平的一种,如果你想让别人感觉你对二进制位理解的很到位,你就可以写这种方法。=的优先级是高于&的所以要加(),那也就是说我们直接写成。因为2的二次幂的二进制中只有一个1,所以,只二进制中只有1个1的时候才能说明是2的2次幂。我个人还是比较推荐移动所求数的二进制位,因为得出来的结果只可能是1或0;那么通过不断的左移,如果左移后&的结果不为0就说明有一个1,如果说我们能让1左移1位就能得到二进制的第二位是多少,然后其实我们也可以直接移动i的二进制位,不断的右移。

HeXIAOxia_的博客 1809

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

求二进制中0/1的个数

今天看到一个题:求整数的二进制中0/1的个数 说实话 我一开始看求1的还好,那个求0的我是真没看懂 上代码 //找0的 int countofZero(int x) { int N = 0; while (x + 1) { N++; x |= (x + 1); } return N; } //找1的 int countOfOne(x) { int N = 0; while(x) { N++;

weixin_45050225的博客 485

【C语言】求二进制中1的个数

求二进制中1的个数

记录学习 834

求x二进制中1的个数的方法(汉明重置/popcount)

因为32位数最多也只能有32个1,用6位表示就足够了;最终返回的就是1的总数。为什么模 63?因为最多有 32 个 1,所以不需要完整地累加全部高位;通过模 63 可以快速提取出低 6 位的和(0~32 之间);是该算法的一种优化写法,避免逐位累加。这是 HAKMEM #169 的原始形式,利用了多位并行加法的技巧;用移位和掩码模拟了逻辑加法器;是一种无需循环的快速人口计数(population count)方法;能适用于早期没有硬件 POPCNT 指令的处理器;

2302_77006429的博客 1631

求一个整数的二进制序列中1的个数

11>>1的补码00000000000000000000000000000101。可知n = n & (n - 1)每执行一次n的二进制序列中1的个数就减少1个。当n=0时退出循环,此时count = 3 也就是二进制中1的个数。可知右移后的二进制序列的最低位只要是1,按位与操作后的结果就是1,也就是说n的二进制序列中有几个1循环就执行几次,大大提高代码效率。这里假设 n = 11 , i = 1。经过n = n & (n - 1)操作后。经过n = n & (n - 1)操作后。

2402_89035880的博客 933

求二进制中1的个数!

移位也能实现本例题,但是有些步骤是多余的,例如假设我们想求1中二进制的个数,因为1中只有第一位是1,而其余剩余31位全是0,那未免有点复杂了,那么我们能否能找到一种方法只来统计1的个数,而不去管0呢。本代码时间上耗费较少,但不容易想到,希望通过本文让读者们了解到此种方法,学习代码就是这种不断积累的过程,多练习,多多进行改善,最后把他彻底搞明白!我们知道当一个数的较低位不够再减一个数字时,其通常可以采取向其上一位进行借位的操作来继续进行求减,如果进行借位之后,那么被借的那一位将会-1,

weixin_71276184的博客 1666

求一个整数存储在内存中的二进制中1的个数

题目:求一个整数存储在内存中的二进制中1的个数 方法一: int num = 10; int count = 0;//计数 while (num) { if (num % 2 == 1) count++; num = num / 2; //等价于:num = num &gt;&gt; 1; } printf("二进制中1的个数为:%d\n", count); 这个是比较...

身在边城 心在编程 370

如何求二进制表示中“1”的个数

刚翻开《编程之美》, 中间就有一道我很眼熟的题,“求二进制中1的个数”。书中的题目描述如下:

AllZone 980

c语言 - 求一个整数储存在内存中的二进制中1的个数 / 求两个数二进制中不同位的个数

写一个函数返回参数二进制中 1 的个数。 本身与本身-1进行按位与&。循环进行,直到本数最终为0结束。 int main() { int num = 15; int i = 0; int count = 0; while (num) { count++; num = num&(num - 1); } printf("二进制序列的中1的个数为%d个\n", count); return 0; } ...

weixin_51136573的博客 179

求一个数的二进制中1的个数(三种方法)

第一种: #include<stdio.h> int Number(unsigned int num) { int tmp,count=0; while (num!=0 ) { tmp = num % 2; num = num / 2; if (tmp == 1) count++; } return count; } int main() { int nu...

qq_42174669的博客 8661

算法题:求二进制位中0的个数

#include using namespace std; //古有求二进制数中1的个数,今有求二进制中0的个数。 int Grial(int x) { int count = 0; while (x + 1) { count++; x |= (x + 1); } return count; } int main() { cout << Grial(1) << endl; return 0; } //为了方便验证,我把求二进制数中1的个数也写下来。 #include using

qq_35392239的博客 1252
上一篇: CPU与GPU并行计算联系与区别
下一篇: Unity3D实现二维物体的来回移动
ljytower
博客等级 码龄12年 119粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值