位运算(一)

位运算的一般应用

功能 例子 运算 去掉最后一位 1110101->111010 x>>1 在最后加0 1110101->11101010 x<

通过如下的例子,来看看位运算在底层的应用:

1.判断是否是2的整数次幂(来自Linux kernel)

uint32_t is_power_two(uint32_t x){
    return !(x&(x-1));
}
uint32_t is_power_two(uint32_t x){
    return x==x&~x+1;
}

方法一

对于无符号数的编码,可以做出如下解释:

[x=\sum _{i=0} ^{w-1} x_i *2^i ]

显然,若该数是2的整数次幂,显然二进制形式是[00…0100…0]的形式,设第 k位为1(从第0位计数),则有:

[x-1=2^k-1=\sum_{i=0}^{k-1}2^i ]

显然,该数的表达方式为 [00...00111...1],与原数进行按位与,结果为0.

方法二

x&~x+1x&-x,首先关于补码的非运算.任意非0的 x总可以找到最后边的1,即可以将 x表示为:

[[x_{w-1},x_{w-2},…,x_{k+1},1,0,0,…,0] ]

从而有:

[-x=[~ x_{w-1},~x_{w-2},…,~x_{k+1},1,0,0,…,0] ]

显然,若 x是2的整数次幂则有 x==x&-x为真.

2.对2的整数次幂取余(来自HashMap)

uint32_t mod_power_two(uint32_t x,uint32_t bucket){
    return x&(bucket-1);
}

对于一个无符号数 x, xmod2^w的作用等价于丢掉该数二进制表示的从w+1位开始的高位,即将该二进制数进行类似截断.例如:

[25\% 16=9—>11001\&01111=01001_2=9_{10} ]

16=2^4,因此取余会将第5位开始的位均设为0,只保留后4位,因此:

[x\ mod\ 2^n=x\&(2^n-1) ]

3.向上取整到2的整数次幂

uint32_t next_power_two(uint32_t x){
    --x;
    x|=x>>1;
    x|=x>>2;
    x|=x>>4;
    x|=x>>8;
    x|=x>>16;
    return ++x;
}

--x是为了保证,这个数不是2的整数次幂. 设这个数可以表示为 1.....,则右移1位得 01......或运算得 11......,继续右移2位,得 0011......或运算得 1111......,最后一次位运算后得 111...111最后返回时 +1遍得到了向上的一个2的整数次幂.

4.判断是否含有奇数个1

bool is_oddones(uint32_t x){
    x^=x>>1;
    x^=x>>2;
    x^=x>>4;
    x^=x>>8;
    x^=x>>16;
    return x&0x1;

}

总的思想: &#x5947;&#x6570;&#x4E2A;1&#x8FDB;&#x884C;&#x5F02;&#x6216;&#x7ED3;&#x679C;&#x4F4D;1,因为只需想方法,将这个数二进制位的所有数进行异或就知道是否有奇数个1了.举了例子,下面这个 数是某个数二进制的低几位.

第一次运算:

​ 1110 1101 1000

​ 0111 0110 1100

^——————————

​ 1001 1011 0100

最右边的0是第0位与第1位异或所得,依次可得 从右往左位 0^1 1^2 2^3 3^4.....(此处的数字为第位数,下同)

第二次运算:

​ 1001 1011 0100

​ 0010 0110 1101

^—————————–

​ 1011 1101 1001

第二排数字的结果分别是 2^3 3^4 4^5 5^6...,故最右边的0是 0^1^2^3,依次再有 1^2^3^4,…

第三次运算:

​ 1011 1101 1001

​ 1011 1101

^—————————–

​ 0110 0100

第二排的数字从最右边开始为 4^5^6^7,依次…….从而结果中,最右边的数代表 0^1^2^3^4^5^6^7

因而,若原数字在原始数据中是第 i位,在最终的结果中,该位代表的即是:

[i\oplus (i+1)\oplus (i+2)\oplus \cdots \oplus (i+30)\oplus (i+31) ]

因为,令 i=0,即最低位的值,即为结果,故最终 x&0x1

5. 1的个数

uint32_t count_one(uint32_t x){
    x=(x&0x55555555)+(x>>1&0x55555555);
    x=(x&0x33333333)+(x>>2&0x33333333);
    x=(x&0x0f0f0f0f)+(x>>4&0x0f0f0f0f);
    x=(x&0x00ff00ff)+(x>>8&0x00ff00ff);
    x=(x&0x0000ffff)+(x>>16&0x0000ffff);
    return x;
}

思想: &#x5206;&#x800C;&#x6CBB;&#x4E4B;

先将32位数分成16份,每份俩部分:

0x55555555= 0101......01

x&0x55555555得到每个小份的第二部分的1情况, x>>1&0x55555555得到每个小份中第一部分的1的情况,相加得到的2位二进制数即为,该小份中1的个数.现在的任务就是将这些数都加起来 .

​ 10 11 01 00 ……

第一次 01 10 01 00

0x33333333= 0011......0011

x&0x33333333将每个2位能单独拿出来,再加上 x>>2&0x33333333就是两个2位数的和(是一个用4位二进制表示的数),即将这16份,合并成8份,4位一组.

​ 01 10 01 00

第二次 0011 0001

0x0f0f0f0f=00001111...00001111

x&0x0f0f0f0f将4位单独拿出来,再加上 x>>4&0x0f0f0f0f就是两个4位数的和.按照这种思想,最后会得到两个16位数的和(按32位表示)这个数的大小就是1的个数.

Original: https://www.cnblogs.com/oasisyang/p/13218500.html
Author: OasisYang
Title: 位运算(一)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585699/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 2020年12月-第01阶段-前端基础-HTML CSS 项目阶段(三)

    品优购项目(三) 1. 首页制作 1). 楼层区 floor 注意这个floor 一个大盒子 包含, 不要给高度,内容有多少,算多少 2). 家用电器模块 这个模块 简单 不需要写…

    Linux 2023年6月8日
    071
  • 【XML】学习笔记第四章-schema

    Schema 概述 作用 与DTD相比Schema的优势 基础命名空间: 模式 引用方法 通过xsi:noNamespaceSchemaLocation引入 通过xsi:shema…

    Linux 2023年6月14日
    089
  • Git报错 error: cannot spawn more: No such file or directory

    问题原因 error: cannot spawn more: No such file or directory 这个错误意思是不存在more指令,我是windows平台,自然这个…

    Linux 2023年6月6日
    099
  • lvs

    1.lvs简介 2.结构体系 3.lvs工作模式及原理 4.配置lvs 4.1 部署lvs-nat模式的httpd负载集群—http协议 4.2 部署lvs-dr模式的…

    Linux 2023年6月13日
    092
  • 剑指offer计划26(字符串中等)—java

    1.1、题目1 剑指 Offer 20. 表示数值的字符串 1.2、解法 这题表示直接上大佬的题解把。。。。代码太长了。有限状态自动机。对状态机一无所知的我一脸懵 1.3、代码 c…

    Linux 2023年6月11日
    097
  • java调用python的惨痛史(无法获取环境变量)

    环境:java,was,python2.6,红帽linux,oracle,python用cx_Oracle事情是这样的,有个需求,需要对数据库进行处理,简单说就是把数据取出来,用p…

    Linux 2023年6月6日
    082
  • MySQL日志管理之通用日志和慢查询日志

    MySQL的通用日志: 用来记录对数据库的通用操作,包括错误的sql语句等信息。 通用日志可以保存在:file(默认值)或 table(mysql.general_log表) my…

    Linux 2023年6月7日
    0128
  • Windows 下日志保存至Linux rsyslog日志服务器

    一、 下载安装 通过https://www.rsyslog.com/windows-agent/windows-agent-download/下载客户端后,按照默认安装完成后即进行…

    Linux 2023年6月6日
    0100
  • wsl2环境搭建

    我电脑配置不高,开虚拟机跑linux总觉得太卡。最近才了解到windows早就上了wsl2——一款较为轻量的虚拟机软件。所以本篇博客偏笔记向,存粹记录以便多次使用。 WSL2安装 …

    Linux 2023年6月7日
    090
  • 每天一个 HTTP 状态码 203

    203 ‘Non-Authoritative Informative’ 直译过来是「非权威信息」的意思… 203 Non-Authoritati…

    Linux 2023年6月7日
    0102
  • sql注入

    一.原理 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有…

    Linux 2023年6月6日
    092
  • histogram的类型详解

    采样点 每隔指定的时间会采集并上报一次数据,称为采样点。 请注意这里采集的是当前瞬间的数据 count 对采样点的 次数累计和(count) bucket 对采样点的 次数进行统计…

    Linux 2023年6月13日
    080
  • Web前端基础精品入门(HTML+CSS+JavaScript+JS)[爱前端]听课笔记2:导航条的制作——css学习仿作马蜂窝

    马蜂窝的首页是非常正能量,青春的网页,首页非常大气 logo在上一篇我们已经制作好,现在我们开始制作导航条 这个导航条字数不等,宽窄不一致,就是所有的li不一样宽,字多就宽,字少就…

    Linux 2023年6月14日
    079
  • pwm驱动

    1.1、参考博客 参考的教程如下: 1.2、什么是PWM 脉冲宽度调制(PWM),是英文”Pulse Width Modulation”的缩写,简称脉宽调制…

    Linux 2023年6月13日
    0110
  • 模型层

    准备阶段 django自带的sqlite3数据库,功能很少,并且针对日期类型不精确 准备步骤 数据库正向迁移命令(将类操作映射到表中) python3 manage.py make…

    Linux 2023年6月7日
    093
  • CentOS——Redis消息订阅发布

    作用: 发布订阅类似于信息管道,用来进行系统之间消息解耦。类似于mq,rebbitmq,rocketmq,kafka,activemq 主要有消息发布者和消息订阅者。 比如:订单支…

    Linux 2023年5月28日
    0105
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球