一. 位操作基础,用一张表描述位操作符的应用规则并详细解释。
二. 常用位操作小技巧,有判断奇偶、交换两数、变换符号、求绝对值。
三. 位操作与空间压缩,针对筛素数进行空间压缩。
四. 位操作的趣味应用,列举了位操作在高低位交换、二进制逆序、二进制中1的个数以及缺失的数字这4种趣味应用。
希望读者能认真学习和亲自上机输入代码进行实验,相信通过本文及适当的练习可以使你对位操作有更加深入的了解,在笔试面试中遇到位操作相关试题能更加从容。
一. 位操作基础
基本的位操作符有与、或、异或、取反、左移、右移这6种,它们的运算规则如下所示:
符号 |
描述 |
运算规则 by MoreWindows |
& |
与 |
两个位都为1时,结果才为1 |
| |
或 |
两个位都为0时,结果才为0 |
^ |
异或 |
两个位相同为0,相异为1 |
~ |
取反 |
0变1,1变0 |
<< |
左移 |
各二进位全部左移若干位,高位丢弃,低位补0 |
>> |
右移 |
各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
|
1.判断奇偶
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。
下面程序将输出0到100之间的所有奇数。
- for (i = 0; i < 100; ++i)
- if (i & 1)
- printf("%d ", i);
- putchar('\n');
2.交换两数
一般的写法是:
- void Swap(int &a, int &b)
- {
- if (a != b)
- {
- int c = a;
- a = b;
- b = c;
- }
- }
可以用位操作来实现交换两数而不用第三方变量:
- void Swap(int &a, int &b)
- {
- if (a != b)
- {
- a ^= b;
- b ^= a;
- a ^= b;
- }
- }
可以这样理解:
第一步 a^=b 即a=(a^b);
第二步 b^=a 即b=b^(a^b),由于^运算满足交换律,b^(a^b)=b^b^a。由于一个数和自己异或的结果为0并且任何数与0异或都会不变的,所以此时b被赋上了a的值。
第三步 a^=b 就是a=a^b,由于前面二步可知a=(a^b),b=a,所以a=a^b即a=(a^b)^a。故a会被赋上b的值。
再来个实例说明下以加深印象。int a = 13, b = 6;
a的二进制为 13=8+4+1=1101(二进制)
b的二进制为 6=4+2=110(二进制)
第一步 a^=b a = 1101 ^ 110 = 1011;
第二步 b^=a b = 110 ^ 1011 = 1101;即b=13
第三步 a^=b a = 1011 ^ 1101 = 110;即a=6
3.变换符号
变换符号就是正数变成负数,负数变成正数。
如对于-11和11,可以通过下面的变换方法将-11变成11
1111 0101(二进制) –取反-> 0000 1010(二进制) –加1-> 0000 1011(二进制)
同样可以这样的将11变成-11
0000 1011(二进制) –取反-> 0000 0100(二进制) –加1-> 1111 0101(二进制)
因此变换符号只需要取反后加1即可。完整代码如下:
- //by MoreWindows( http://blog.csdn.net/MoreWindows )
- #include <stdio.h>
- int SignReversal(int a)
- {
- return ~a + 1;
- }
- int main()
- {
- printf("对整数变换符号 --- by MoreWindows( http://blog.csdn.net/MoreWindows ) ---\n\n");
- int a = 7, b = -12345;
- printf("%d %d\n", SignReversal(a), SignReversal(b));
- return 0;
- }
4.求绝对值
位操作也可以用来求绝对值,对于负数可以通过对其取反后加1来得到正数。对-6可以这样:
1111 1010(二进制) –取反->0000 0101(二进制) -加1-> 0000 0110(二进制)
来得到6。
因此先移位来取符号位,int i = a >> 31;要注意如果a为正数,i等于0,为负数,i等于-1。然后对i进行判断——如果i等于0,直接返回。否之,返回~a+1。完整代码如下:
- //by MoreWindows( http://blog.csdn.net/MoreWindows )
- int my_abs(int a)
- {
- int i = a >> 31;
- return i == 0 ? a : (~a + 1);
- }
现在再分析下。对于任何数,与0异或都会保持不变,与-1即0xFFFFFFFF异或就相当于取反。因此,a与i异或后再减i(因为i为0或-1,所以减i即是要么加0要么加1)也可以得到绝对值。所以可以对上面代码优化下:
- //by MoreWindows( http://blog.csdn.net/MoreWindows )
- int my_abs(int a)
- {
- int i = a >> 31;
- return ((a ^ i) - i);
- }
注意这种方法没用任何判断表达式,而且有些笔面试题就要求这样做,因此建议读者记住该方法(^_^讲解过后应该是比较好记了)。
实际应用:
位运算存储数据
利用位运算存储数据,主要是为了减少程序占用的内存。以int数据为例子,如果按照十进制的方式存储数据,一个32位的int变量只能存储一个数值,而如果使用二进制方式存储数据(缺点是只能存储0或1两个数据)则可以存储32个数据,将极大的节约内存。例如,在一个int变量的从右侧开始倒数第2位存储数据,则存储和读取数据的代码如下所示:
//存储数值1
bData = bData |(1 << (2 - 1));
//存储数值0
bData = bData & (~(1 << (2 - 1));
//读取数据
int n = bData & (1 << (2 - 1));
点评:在该代码中,将需要存储的数据(0或1)存储在变量bData的倒数第二位中,所以在存储时,则只需要将倒数第二位的数值改变,其他位的数值不改变即可。所以在存储1时,不论bData的数值是多少,只需要和二进制数据10进行位或运算就可以将倒数第二位置1,而需要存储0时,则需要bData和0xfffffffd进行位与运算,即可达到清零倒数第二位的目的。
需要注意的是,有些可能会认为在存储数值0时,会使用如下的代码实现:
其实这样是错误的,因为0无论左移多少位都还是0,这样在进行位或运算时,0和1位或得到的结果会是1,无法实现设置对应的位为0的目的,所以需要使用以上的代码进行实现。
异或位运算简单加密
利用位运算的计算速度快,以及异或的特性(和同一个数字异或两次还是自身),可以用来简单加密数据,且加解密的速度会非常快。这种加密方式强度比较低,但是可以用于一般的加解密任务。例如,假设密匙是数字123,则加解密一个byte数组的代码如下:
byte key = 123;
//依次加密的代码
for(int i = 0;i < b.length;i++){
b[i] = (byte)(b[i] ^ key); //利用异或加密
}
//解密的代码
for(int i = 0;i < b.length;i++){
b[i] = (byte)(b[i] ^ key); //利用异或解密
}
点评:在该代码中,对数组b使用密匙key进行加密,加密的过程是将数组b中每个元素和key进行异或,加密以后的数据可以在实际应用中进行存储或网络传输,而解密时的操作和加密时一样,使用这种简单的加密方式虽然保密性不高,但是加解密的速度确实是很值得称赞的。
高效对比两个数组有几个数字相同(竞彩投注与开奖的数字对比)
一组字符 1,0,3,1,3,31,31,3,1,0,0,0,3,3
一组校准字符 1,0,0,1,1,3,0,1,0,1,0,3,1,3
要如何高效的确定有几个是相同的呢 .
利用异或的:两个元素异或结果为0,则相同。
代码:产生两个100000长度数组元素为100以内的随机数(元素一一对应),比较两者有哪些相同的元素,测试结果:两个数直接对比与异或对比相差不大,而且异或有时比直接对比还慢。(对比的速度与元素值的大小有关系如果为10000以内的随机数测试结果又不一样)
public class Test { public static void main(String[] args) { int len = 100000; int[] arr1 = new int[len]; int[] arr2 = new int[len]; for (int i = 0; i < len; i++) { arr1[i] = RandomUtils.nextInt(100); arr2[i] = RandomUtils.nextInt(100); } long start = System.currentTimeMillis(); int s = 10000; int count = s; while (count > 0) { cycleEqual(arr1, arr2); count--; } System.out.println("cycleEqual time: " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); count = s; while (count > 0) { cycleExclusiveOR(arr1, arr2); count--; } System.out.println("cycleExclusiveOR time: " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); count = s; while (count > 0) { haflCycleExclusiveOR(arr1, arr2); count--; } System.out.println("haflCycleExclusiveOR time: " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); count = s; while (count > 0) { haflCycleEqual(arr1, arr2); count--; } System.out.println("haflCycleEqual time: " + (System.currentTimeMillis() - start)); } /** * 循环等于对比 * @param arr1 * @param arr2 */ public static void cycleEqual(int[] arr1, int[] arr2) { for (int i = 0; i < arr1.length; i++) { if (arr1[i] == arr2[i]) { // System.out.print(arr1[i] + ","); continue; } } // System.out.println(); } /** * 循环异或对比 * @param arr1 * @param arr2 */ public static void cycleExclusiveOR(int[] arr1, int[] arr2) { for (int i = 0; i < arr1.length; i++) { if ((arr1[i] ^ arr2[i]) == 0) { // System.out.print(arr1[i] + ","); continue; } } // System.out.println(); } /** * 减半循环异或对比 * @param arr1 * @param arr2 */ public static void haflCycleExclusiveOR(int[] arr1, int[] arr2) { int len = arr1.length; int halfLen = len/2; for (int i = 0; i < halfLen; i++) { if ((arr1[i] ^ arr2[i]) == 0) { } if((arr1[len - i - 1] ^ arr2[len - i - 1]) == 0){ } } } /** * 减半循环对比 * @param arr1 * @param arr2 */ public static void haflCycleEqual(int[] arr1, int[] arr2) { int len = arr1.length; int halfLen = len/2; for (int i = 0; i < halfLen; i++) { if ((arr1[i] == arr2[i])) { } if((arr1[len - 1 - i] == arr2[len - 1 - i])){ } } } }
结果:
cycleEqual time: 3969
cycleExclusiveOR time: 3984
haflCycleExclusiveOR time: 3187
haflCycleEqual time: 3219
位运算
>> 右移 右移一位相当于除2,右移n位相当于除以2的n次方。
例: 8>>2 相当于 8/2 = 4
<< 左移 左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方
例: 3<<2 相当于 3*4 = 12
异或两次还是原来本身
例: a = a^b^b
参考:
对比尽量减少循环次数与if次数
java位运算 位运算符在HashMap中运用的一个场景
相关推荐
拖拉机变速箱箱体工艺及夹具设计.rar
birch_door_bottom
台灯底座塑料模设计.rar
塑料瓶自动封口机(自动容器封口机)设计.rar
液压电梯与立体车库的组合设计.rar
barrel_top_open
activator_rail
内容概要:本文介绍了计算机专业毕业设计的选题方向,涵盖软件开发、人工智能、数据分析、网络安全四大领域。在软件开发类中,包括基于Spring Boot和Vue.js的在线教育平台、基于Android的健身管理APP、企业资源规划(ERP)系统等;人工智能类涉及基于深度学习的图像识别垃圾分类系统、智能客服系统、机器人路径规划算法等;数据分析类则关注电商平台用户行为分析、医疗大数据分析、社交媒体舆情分析;网络安全类有基于入侵检测系统的网络安全防护体系、云存储数据安全加密与访问控制、无线网络安全漏洞检测与防范系统。每个方向都给出了具体的项目示例,并简述了项目的核心技术和应用场景。; 适合人群:计算机相关专业的本科毕业生,特别是正在准备毕业设计的学生。; 使用场景及目标:帮助学生根据个人兴趣和技术背景选择合适的毕业设计课题,明确研究方向和预期成果,为顺利完成毕业设计提供参考。; 其他说明:毕业设计是学生将理论知识转化为实际应用的重要环节,选题时应充分考虑自身的技术积累和兴趣点,确保项目的可行性和创新性。同时,建议学生在选题过程中积极与导师沟通,获取更多专业指导和支持。
内容概要:本文探讨了三种去除玻璃窗反射的方法及其实验结果。第一种方法是基于平滑性的单图像层分离法,适用于静态图像,假设背景层比反射层更清晰,通过高斯滤波和梯度提取分离两层。第二种方法是基于运动的多帧图像分离法,利用连续拍摄的图像序列,通过边缘检测、稀疏运动场计算、分类、稠密运动场插值和图像变形实现反射与背景分离。第三种方法是基于稀疏先验的用户辅助分离法,需要用户提供反射层和背景层的边缘信息,通过期望最大化(EM)或迭代重加权最小二乘优化(IRLS)算法进行分离。; 适合人群:计算机视觉领域的研究人员、图像处理工程师以及对图像去反射技术感兴趣的开发者。; 使用场景及目标:①从单张照片中去除玻璃窗反射,适用于摄影后期处理;②从连续拍摄的图像序列中去除反射,适用于智能手机和相机的实时图像处理;③通过用户标记辅助去除复杂场景中的反射,适用于特定应用场景下的图像修复。; 其他说明:本文详细介绍了每种方法的算法步骤和实验结果,指出了各方法的优点和局限性。Smoothness Approach适用于简单背景和聚焦良好的图像,Motion Approach需要多帧图像但对普通情况表现良好,User-assisted Separation with Sparse Prior则需要用户干预且内存开销较大。
内容概要:本文档详细介绍了基于SSH(Struts、Spring、Hibernate)框架的医院在线挂号系统的设计与实现。随着互联网技术的发展,传统医院挂号方式因效率低下、耗时等问题亟待改进。该系统旨在解决患者挂号难、排队时间长的问题,通过在线平台提供便捷的预约挂号服务。系统采用SSH框架,结合MySql数据库,确保了系统的稳定性、安全性和易维护性。系统的主要角色包括患者和管理员,患者可以查询医院及医生信息、注册登录、预约挂号、取消挂号、更改个人信息;管理员则负责更新医院和医生信息、发布公告、管理用户信息等。系统设计了导航引导新用户操作,分离了用户和管理员登录入口,确保了系统的易用性和安全性。总体测试结果显示,该网站基本符合用户需求,达到了较高的用户满意度。 适合人群:计算机科学、软件工程及相关专业的本科生或研究生,尤其是对医院信息系统开发感兴趣的读者。 使用场景及目标:①适用于医院信息化建设项目,特别是需要改进挂号流程、提高医疗服务效率的场景;②为开发人员提供一个基于SSH框架的医院在线挂号系统的实现案例,帮助理解SSH框架在实际项目中的应用;③为医院管理层提供一种现代化的挂号管理方案,优化资源配置,提高患者满意度。 其他说明:该系统不仅提高了医院的管理效率和服务质量,也为患者提供了便捷的挂号方式,减少了不必要的等待时间。系统采用的技术栈(SSH框架、MySql数据库等)具有良好的可扩展性和复用性,便于后续功能的扩展和技术升级。此外,系统在设计时充分考虑了用户体验,通过导航设计和功能分离等方式,确保了系统的易用性和安全性。
该资源为joblib-0.9.0b2-py2.7.egg,欢迎下载使用哦!
一种window下使用mac字体
关于新闻事件的命名实体的测试集数据
内容概要:本文介绍了DARPA的Scalable On-Array Processing(SOAP)项目,旨在通过可扩展算法和分布式架构打破数字阵列瓶颈,提升多波束、多功能RF操作的性能。会议议程包括项目概述、技术挑战、未来扩展计划以及提案提交指南。关键技术挑战包括处理瓶颈和数据传输瓶颈,解决方法涉及分布式处理、迭代算法和光互连等。项目评估标准涵盖科学与技术价值、对DARPA任务的潜在贡献及成本合理性。提案需详细描述如何克服技术难题并满足项目目标。 适合人群:具备雷达系统、信号处理和电子工程背景的研究人员和技术专家,特别是关注国防科技发展的专业人士。 使用场景及目标:①探索大规模数字阵列的高效处理方法;②开发用于干扰抑制、信号增强和其他阵列应用的新算法;③评估分布式硬件架构在实际环境中的表现。 其他说明:提案者应熟悉DARPA的工作流程和合同管理要求,提前准备摘要并积极参与问答环节,确保提案符合项目指南并在规定时间内提交。此外,提案需展示创新性和可行性,并明确阐述技术路径和预期成果。
基于Python的m3u8下载器.zip
bamboo_block
闹钟后盖模具设计及型腔仿真加工.zip
制定三头钻底座(图5-29)的加工工艺,设计钻铰Ф8H7孔的钻床夹具设计.rar
内容概要:本文档提供了基于STM32实现的衣物智能护理机控制应用案例的C++源码框架,整合了温湿度监测、自动除皱、杀菌及烘干功能。硬件配置包括主控芯片STM32F103ZET6、DHT11温湿度传感器、UV-C紫外线杀菌灯、衣物重量压力传感器、继电器控制的PTC加热器、直流风扇、步进电机驱动的机械臂以及ESP8266 WiFi通信模块。控制源码采用HAL库实现,涵盖了外设初始化、PID算法控制烘干、紫外线杀菌控制、机械除皱算法、远程命令处理等功能。文档详细描述了系统的硬件配置、关键外设驱动类实现、多模式控制架构、安全保护机制、扩展接口以及典型工作流程; 适合人群:具有嵌入式系统开发基础,对STM32和C++有一定了解的研发人员; 使用场景及目标:①学习如何使用STM32进行智能设备的控制开发;②掌握温湿度监测、自动除皱、杀菌及烘干功能的具体实现方法;③了解工业级控制逻辑和安全保护机制的设计; 阅读建议:此资源不仅包含代码实现,还涉及硬件配置和系统架构设计,建议读者结合实际硬件进行调试和实践,以加深理解。
python Python_1502_省市区三级地址库_chy5.zip