令人赞叹的位运算
时间:2022-07-23
本文章向大家介绍令人赞叹的位运算,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
想必大家每次阅读第三方源码时,都觉得其中的位运算很酷,让人神往又抓狂。为了搞懂那些操作的具体含义,想去深入了解那些魔法代码背后的原理。
之前我也写过一篇文章谈了一些面试中可能遇到的算法题,今天更多的是一些用法的总结。
我们先回顾下常见的位运算符:
- & 与运算 两个位都是 1 时,结果才为 1,否则为 0, 如 :1 0 0 1 1 & 1 1 0 0 1 =1 0 0 0 1
- |或运算 两个位都是 0 时,结果才为 0,否则为 1, 如 :1 0 0 1 1 | 1 1 0 0 1 =1 1 0 1 1
- ^ 异或运算,两个位相同则为 0,不同则为 1, 如 :1 0 0 1 1 ^ 1 1 0 0 1 =0 1 0 1 0
- ~ 取反运算,0 则变为 1,1 则变为 0, 如:~ 1 0 0 1 1 =0 1 1 0 0
然后我们再来看看一些常见的技巧。
一,我们知道我们的字符在计算机底层都是数字表示的,恰巧英文字符在ASCII 编码里通过位运算就能进行大小写转换。
- 利用或操作 | 和空格将英文字符转换为小写。
('a' | ' ') = 'a'
('A' | ' ') = 'a'
- 利用与操作 & 和下划线将英文字符转换为大写。
('b' & '') = 'B'` `('B' & '') = 'B'
- 利用异或操作 ^ 和空格进行英文字符大小写互换。
('d' ^ ' ') = 'D'
('D' ^ ' ') = 'd'
二,异或的性质非常方便
- 可以判断两个数是否异号:
int x = -1, y = 2; boolean f = ((x ^ y) < 0); // true
int x = 3, y = 2; boolean f = ((x ^ y) < 0); // false
- 也可以用来交换两个数:
int a = 1, b = 2;
a ^= b;
b ^= a;
a ^= b;
// 现在 a = 2, b = 1
三,判断奇偶数
- 只要根据数的最后一位是 0 还是 1 来决定即可,为 0 就是偶数,为 1 就是奇数。 ``` if(0 == (a & 1)) { //偶数 }
四,符号交换
* 交换符号将正数变成负数,负数变成正数。
int reversal(int a) { return ~a + 1; }
整数取反加1,正好变成其对应的负数(补码表示);负数取反加一,则变为其原码,即正数。
五,求绝对值
整数的绝对值是其本身,负数的绝对值正好可以对其进行取反加一求得,即我们首先判断其符号位(整数右移 31 位得到 ),然后根据符号进行相应的操作int
int abs(int a) { int i = a >> 31; return i == 0 ? a : (~a + 1); }
六,取反实现+1,-1(不过我感觉没啥用)
int n = 1; n = -~n; // 现在 n = 2
```
int n = 2;
n = ~-n;
// 现在 n = 1
七,位操作统计二进制中 1 的个数 统计二进制1的个数可以分别获取每个二进制位数,然后再统计其1的个数,此方法效率比较低。不过 n & (n - 1) 可以消除最后一个 1,所以可以用一个循环不停地消除 1 同时计数,直到 n 变成 0 为止。
while (n != 0) {
n = n & (n - 1);
res++;
}
怎么样,是不是感觉自己奇怪的知识又增加了??总体而言,虽然这些技巧有的提高了性能,有的简化了代码,但不是所有代码都那么好理解,大家还需要结合实际场景去理解这些技巧,从实际的题目中去找到它们的优势,它们的意义。happy coding~
- 作业调度框架 Quartz.NET 2.0 beta 发布
- 系统捕获异常并发送到服务器
- 当调用GetAuthorizationGroups() 的错误-“试图访问卸载的应用程序域“(Exception from HRESULT: 0x80131014)解决方案
- WCF 4.0路由服务Routing Service
- ExpandableListView简单应用及listview模拟ExpandableListView
- 文件句柄与文件描述符
- android GifView分享
- VAE、GAN、Info-GAN:全解深度学习三大生成模型
- android获取设备唯一标示
- 如果正确读取SQL Server中的扩展事件?
- android自定义xmls文件属性
- 分布式系统中的RPC请求经常出现乱序的情况 写一个算法来将一个乱序的序列保序输出
- jsoup详解
- 用LogParser对IIS 日志进行分析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Angular父子Component之间的事件通知机制
- dotnet OpenXML 解析 PPT 文本字体获取详解
- R练习50题 - 第一期
- [889]python处理HTML转义字符
- python 利用jinja2模板生成html代码实例
- vue项目使用 富文本 封装
- typescript基础篇(5):类
- .Net微服务实战之Kubernetes的搭建与使用
- 使用Prometheus监控Golang服务-基于YoyoGo框架
- 使用jedis面临的非线程安全问题
- 基于UVM的UART验证环境
- 潘石屹用Python解决100个问题 | 打印菱形
- Android:源码解析 Dialog的窗口机制
- Java|获取图片rgb值
- (数据科学学习手札93)利用geopandas与PostGIS进行交互