C/C++中__builtin_popcount()的使用及原理

2023-11-10

这个函数功能:返回输入数据中,二进制中‘1’的个数

对于不同的使用类型,可以采用采用以下函数:

__builtin_popcount = int
__builtin_popcountl = long int
__builtin_popcountll = long long

1. 二分法,源码采用的方法

主要思路是:将相邻两位相加,可以实现用二进制来表示输入数据中‘1’的个数。然后依次将上半部分和下半部分相和并实现计数。

unsigned popcount (unsigned u)
{
    u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
    u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
    u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
    u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
    u = (u & 0x0000FFFF) + ((u >> 16) & 0x0000FFFF);
    return u;
}

算法案例如下:
这个二分法的原理:
用8位二进制数来做示范好了,例如 u = 10110011。
10110011
00010001 //每两位取1位,即取偶数位, u & 01010101
01010001 //取奇数位并右移一位, (u >> 1) & 01010101
---------------
01100010 //上面两数相加,赋值给u,注意每两列相加的结果不会进位到第三列
00100010 //每四位取低两位, u & 00110011
00010000 //每四位取高两位并右移两位, (u >> 2) & 00110011
---------------
00110010 //上面两数相加,赋值给u
00000010 //每八位取低四位, u & 00001111
00000011 //每八位取高四位并右移四位,(u >> 4) & 00001111
---------------
00000101 //上面两数相加,赋值给u
最终结果 u = 5。
在这里插入图片描述

方法二:末位清零

这个方法还是很常见的,利用一个数字减1之后,原来数字最后一个‘1’的位置一定会变成0,然后利用与&操作来实现清零最后一位。

unsigned popcnt (unsigned u)
{
    unsigned ret = 0;
    while (u)
        {
        u = (u & (u - 1));    // 将 u 最右边的 1 清除
        ret ++;
        }
    return ret;
}

方法三:哈希法(查表法)

这种方法感觉是最快的一种,但是也是最笨的吧。(可是我也没想到这种做法),实现原理就是把1个字节(8位),每个数字(0~255)所对于的个数记录下来,一直查表就可以了。

char poptable [256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
unsigned __builtin_popcount (unsigned u)
{
    return poptable [u & 0xFF] + poptable [(u >> 8) & 0xFF] + poptable [(u >> 16) & 0xFF] + poptable [(u >> 24) & 0xFF];

反思:这种方法自己竟然没有想到,虽然看起来很笨,但是实际应用中,应该是最高效的实现。
思路上思考算法时,最好将时间最快,空间最小当作两个极端情况来思考。

参考博客:

C/C++中__builtin_popcount()的使用及原理

__builtin_popcount defined only for int?
GG的四种方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C/C++中__builtin_popcount()的使用及原理 的相关文章

随机推荐

  • 高并发与多线程区别

    开发十年 就只剩下这套Java开发体系了 gt gt gt 1 高并发 高并发是一种状态 如果大量请求访问网关接口 这种情况会发生大量执行操作 如数据库操作 资源请求 硬件占用等 这就需要对接口进行优化 而多线程是处理高并发的一种手段 2
  • 显示器已入手,我快成显示器采购专家了

    上次发了一个请粉丝推荐显示器的文章 想入手显示器 恳请粉丝带我推荐 必有重谢 文章发出后 得到了很多粉丝的回复 一 粉丝留言 粉丝的热情让我再次懵逼 那么多推荐 我到底该选择哪一款 我是个处女座啊 性格逼着我必须做出最佳选择 没办法 我硬着
  • 【Redis】Redis 的学习教程(八)之 BitMap、Geo、HyperLogLog

    Redis 除了五种常见数据类型 String List Hash Set ZSet 还有一些不常用的数据类型 如 BitMap Geo HyperLogLog 等等 它们在各自的领域为大数据量的统计 1 BitMap BitMap 计算
  • C语言:判断一个数是否是偶数

    include
  • mysql人力资源管理系统代码_jsp+mysql人力资源 人力资源管理系统 - 下载 - 搜珍网...

    压缩包 renli1 rar 列表 太原理工 王泽汇 毕设最终版 db rlcp sql 太原理工 王泽汇 毕设最终版 rlcp classpath 太原理工 王泽汇 毕设最终版 rlcp externalToolBuilders com
  • 有些论文附的arXiv:XXXX是什么意思

    什么是arXiv org 先看看来自wikipedia的定义 The arXiv pronounced archive as if the X were the Greek letter Chi is an archive for elec
  • linux下对java程序生成dump文件

    1 首先 java程序启动在linux 怎么生成dump文件 1 第一步 首先你需要得到java程序的PID 最简单的方法使用如下命令 ps ef grep java 或者如果是docker启动的 springboot服务 也可以使用本命令
  • Android 基础知识4-3.11 Adapter(适配器)详解

    一 简介 Adapter是连接后端数据和前端显示的适配器接口 是数据和UI View 之间一个重要的纽带 在常见的View ListView GridView 等地方都需要用到Adapter 如下图直观的表达了Data Adapter Vi
  • 在区块链上开发可更新的智能合约

    由于区块链不可篡改的特性 智能合约一旦部署在区块链上 其执行的逻辑就无法再更改 长期来看 这个重要的特性反而限制了智能合约的弹性和发展 接下来要介绍如何设计及部署合约才能让合约在需要时可以更新 但这里的更新意思不是修改已经部署的合约 而是部
  • 【一网打尽】独立重复事件——常见概率分布

    文章目录 定义 伯努利 Bernouli 试验 n重伯努利试验 伯努利过程 泊松 Poisson 过程 概率分布的意义 0 1分布 伯努利分布 二项 Binomial 分布 负二项 NegativeBinomial 分布 几何 Geomet
  • 区块链的数据结构(一)——区块、链

    区块 区块 block 由区块头 block header 和交易列表 transaction list tx list 组成 block之间通过block header的hash连接成了一个链表结构 但这个链表不同于普通链表 1 bloc
  • JAVA根据PDF文件生成图片

    PDF文件生成图片 实现功能 根据上传的PDF文件 生成图片文件 单页PDF 生成图片文件 多页PDF 则生成zip压缩包 一 文件生成效果 二 引入所需maven依赖 项目采用springboot框架
  • python学习1.2字符串

    一 给变量赋值字符串的时候 要用引号引起来 可以用单引号或者双引号 1 输入 message hello world print message 输出 hello world 2 输入 message hello world print m
  • Java操作ElasticSearch相关内容

    Java连接ES 创建Maven工程 导入依赖
  • 常用遥感SIF和GPP数据集

    一 综述文章 总结一下数据和文章 害怕时间久了忘了 前两篇介绍了SIF 最后一篇介绍了光合作用 1 Remote sensing of solar induced chlorophyll fluorescence SIF in vegeta
  • 【车辆检测】基于背景差分法实现道路行驶车辆检测附matlab代码

    1 简介 该方法的基本思想是 将采集到的车辆图像的每一帧都与一个不含运动车辆的静止参考帧做差值运算 从而突出目标图像 通过分析与处理对车辆计数 其优点是算法简单 处理速度快 且差分结果能直接反应运动目标的位置 形状以及大小等 实用性较强 其
  • css flex布局 —— 容器属性 align-content

    align content 属性定义了多根轴线的对齐方式 如果项目只有一根轴线 该属性不起作用 如果只有一根轴线 align content 几乎等同于 align items 容器属性 align content 生效的条件是 必须显式的
  • 高校校园网使用的认证客户端常见故障自查- 神州数码客户端

    神州数码客户端常见故障自查 一 客户端认证成功前故障 1 接上网线后网卡灯不亮 确定自己电脑网卡带灯 注 测试期间最好是不要接交换机 直接接墙上端口 参考方案 A 更换网线 B 如确认是端口故障 则请致电网络中心报修等待人过来维修 2 如果
  • (每日一练)MATLAB生成斐波那契数和数列

    今天 我学习的内容是利用MATLAB生成斐波那契数 先来介绍一下 斐波那契数列最初是用来解决兔子问题的 问题如下 一个人把一对兔子放在一个四面被墙包围的地方 假设每对兔子每个月都生一对新兔子 不 考虑伦理问题 那么一年可以从这对兔子中生产多
  • C/C++中__builtin_popcount()的使用及原理

    这个函数功能 返回输入数据中 二进制中 1 的个数 对于不同的使用类型 可以采用采用以下函数 builtin popcount int builtin popcountl long int builtin popcountll long l