Java位运算及移位运算
java中能表示整数数据类型的有byte、short、char、int、long,在计算机中占用的空间使用字节描述,1个字节使用8位二进制表示。
| 数据类型 | 字节数 | 二进制位数 | 表示范围 | 默认值 |
|---|---|---|---|---|
byte | 1 | 8 | -27 – 27-1 | 0 |
char | 2 | 16 | 0 – 216-1 | '\u0000' (代表字符为空 转成int就是0) |
short | 2 | 16 | -215 – 215-1 | 0 |
int | 4 | 32 | -231 – 231-1 | 0 |
long | 8 | 64 | -263 – 263-1 | 0L |
1. 原码、反码、补码
使用位运算前需要先弄清楚这几个概念
1.1. 原码
原码也叫机器码,整数的二进制形式表示,最高位为符号位。1表示负数,0表示正数,除去符号位后剩余其他的所有位是该整数的绝对值的二进制值。
int a = 7; //原码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//原码二进制表示为:10000000 00000000 00000000 00000111
1.2. 反码
反码需要区分是正数还是负数,正数的反码跟原码相同,负数的反码是除符号位外,其他位取反(即负数的最高位是1不变,其他位0变成1,1变成0)。
int a = 7; //反码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//反码二进制表示为:11111111 11111111 11111111 11111000
1.3. 补码
补码也需要区分是正数还是负数,正数的补码跟原码相同,负数的补码是反码最低位加1。
int a = 7; //补码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//补码二进制表示为:11111111 11111111 11111111 11111001
说完了概念,其实这里的原码是方便给人看的,对于计算机运算来说都是使用补码形式操作。以下的位运算和移位运算都是基于补码进行的。
2. 位运算
2.1. 位运算术语解释
| 位运算符 | 含义 | 解释 | 备注 |
|---|---|---|---|
& | 按位与 | 两个整数按位对齐,当对齐的两位同时为1则结果为1,否则为0 | |
| ` | ` | 按位或 | 两个整数按位对齐,当对齐的两位只要有一个为1则结果为1,否则为0 |
~ | 按位非 | 只能适用于一个整数的自身操作,按位取反,即1变成0,0变成1 | 单目运算符 |
^ | 按位异或 | 两个整数按位对齐,当对齐的两位相同时为0,否则为1 |
2.2. 位运算示例
我们以上面的int a = 7和int b = -7举例位运算的操作。
a的补码二进制为:00000000 00000000 00000000 00000111
b的补码二进制为:11111111 11111111 11111111 11111001
1、a&b
按位与的结果补码为:00000000 00000000 00000000 00000001
因为最高位为0,所以为正数,`正数的原码反码补码都相同`,所以原码也为:
00000000 00000000 00000000 00000001
转换成十进制的结果就是1。
2、a|b
按位或的结果补码为:11111111 11111111 11111111 11111111
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11111110
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000001
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是1,所以最后按位或的结果就是-1。
3、a^b
按位或的结果补码为:11111111 11111111 11111111 11111110
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11111101
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000010
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是2,所以最后按位或的结果就是-2。
4、~a
取反结果(补码形式):11111111 11111111 11111111 11111000
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11110111
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00001000
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是8,所以最后按位或的结果就是-8。
5、~b
取反结果(补码形式):00000000 00000000 00000000 00000110
最高位为0,所以是正数。正数的原码反码补码都相同,所以转换成十进制结果为6。
2.3. 位运算应用于boolean操作
&(与)、|(或)这两个位运算适用于boolean判断,在这两个运算符的前后的条件都会计算,不像java里的条件判断符&&(并且) ||(或者)会短路,判断符之前的满足条件后,那么判断符之后的表达式不再计算。
public static void main(String[] args) {int a = 5;if (a < 0 & a++ > 0) {}System.out.println("&条件后a=" + a);if (a > 0 | a++ > 0) {}System.out.println("|条件后a=" + a);if (a < 0 && a++ > 0) {}System.out.println("&&条件后a=" + a);if (a > 0 || a++ > 0) {}System.out.println("||条件后a=" + a);
}
输出结果为:

第一个判断a < 0 & a++ > 0前一个判断已经是false了,但是使用&连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于6。
第二个判断a > 0 | a++ > 0前一个判断已经是true了,但是使用|连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于7。
第三个判断a < 0 && a++ > 0前一个判断已经是false了,使用&&连接的不会再计算后一个表达式的值,所以a的值不变。
第四个判断a > 0 || a++ > 0前一个判断已经是true了,使用||连接的不会再计算后一个表达式的值,所以a的值不变。
3. 移位运算
3.1. 移位运算术语解释
| 移位运算符 | 含义 | 解释 |
|---|---|---|
<< | 左移 | 补码高位(不包括符号位)去掉指定位数,然后剩下的位数整体向左移动指定位数,低位使用0补齐 |
>> | 右移 | 补码低位去掉指定位数,然后剩下的位数整体向右移动指定位数,高位补上符号位(即正数补0,负数补1) |
>>> | 无符号右移 | 这个主要是针对于负数来说的,补码低位去掉指定位数,然后剩下的位数整体向右移动指定位数,高位(包括符号位)全部补上0 |
移位运算也是基于补码来操作的,因为是采用二进制,所以左移n位相当于该数乘以2的n次方、右移及无符号右移n位相当于该数除以2的n次方,但是无符号右移是相对于负数来说的,把符号位和其他高位都置为0。
3.2. 移位运算示例
我们仍以上面的int a = 7和int b = -7举例移位运算的操作。
a的补码二进制为:00000000 00000000 00000000 00000111
b的补码二进制为:11111111 11111111 11111111 11111001
1、a<<2
符号位不变,高位去掉两位,整体左移两位,低两位补0,结果为:
补码:00000000 00000000 00000000 00011100
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:28
2、a>>2
符号位为0,正数,则符号位不变,低位去掉两位,整体右移两位,高两位补0,结果为:
补码:00000000 00000000 00000000 00000001
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1
3、a>>>2
符号位为0,正数,低位去掉两位,整体右移两位,高两位(包括符号位)补0,结果为:
补码:00000000 00000000 00000000 00000001
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1
4、b<<2
符号位不变,高位去掉两位,整体左移两位,低两位补0,结果为:
补码:11111111 11111111 11111111 11100100
高位为1即负数
反码=补码-1,得到反码:11111111 11111111 11111111 11100011
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00011100
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是28,所以最后按位或的结果就是-28。
5、b>>2
符号位为1,负数,低位去掉两位,整体右移两位,高两位补1,符号位为1,结果为:
补码:11111111 11111111 11111111 11111110
高位为1即负数
反码=补码-1,得到反码:11111111 11111111 11111111 11111101
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000010
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是2,所以最后按位或的结果就是-2。
6、b>>>2
符号位为1,负数,低位去掉两位,高两位(包括符号位)都补0,结果为:
补码:00111111 11111111 11111111 11111110
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1073741822。
3.3. 移位运算注意事项
1、byte、short、char类型的整数再移位操作时会自动向上转为int类型后再操作移位。
2、int类型占32位,long类型占64位,当对这两个类型移位超出位数时,相当于对要移动的位数取余再移位,例如a<<32位,取余为0,相当于不移动,a<<34,取余为2相当于左移2位。long类型同理,只是对64取余。
4. 应用
1、不利用中间值,交换两个整数
可推导出的结论是a ^ b ^ a = b,a ^ b ^ c = a ^ (b ^ c)。所以对于两个整数a,b交换可以使用异或位运算。
public static void main(String[] args) {int a = 5, b = 3;System.out.println("a=" + a + "\tb=" + b);a = a ^ b;b = a ^ b;a = a ^ b;System.out.println("a=" + a + "\tb=" + b);
}
输出结果:

2、判断一个正数的奇偶性
x & 1 == 0 则为偶数,否则为奇数。因为整数的二进制表示后,最后一位的0和1就表示了该值的奇偶性,&1之后相当于除了最后一位,其他位全清0了,最后一位若是1,则与的结果才为1,说明是奇数,最后一位为0,则与的结果是0,说明是偶数。
3、判断一个正数是不是2的幂次方
使用n&(n-1) == 0则为偶数,否则为奇数。因为2的次方数,除了高位的一个1外,后面的数据全部都是0,也就是说2的次方数的二进制形式里只有一个1,其他全部是0,减1后得到的二进制,1所在位变成0,1后的其他位都会变成1,所以与原二进制每一位都不相同,使用&后结果为0,则可以证明为偶数
4、计算一个二进制数中1的个数
int a = 15;
int count = 0;
while (a != 0) {if ((a & 1) == 1) {count++;}a = a >> 1;
}
System.out.println(count);
输出结果:

通过&1结果为1,说明最末一位是1,则可通过不断>>1并判断1的个数是否加1,直到这个数的值变为0为止。
相关文章:
Java位运算及移位运算
java中能表示整数数据类型的有byte、short、char、int、long,在计算机中占用的空间使用字节描述,1个字节使用8位二进制表示。 数据类型字节数二进制位数表示范围默认值byte18-27 – 27-10char2160 – 216-1\u0000 (代表字符为空 转成int就是0)short216-…...
上界通配符(? extends Type)
在Java中,? extends Type是一个上界通配符,表示参数化类型的上限是Type。这意味着容器可以持有Type类型的任何对象或者Type的子类型对象。 使用场景 这种类型的通配符常用于泛型方法中,允许方法接受Type的实例或其子类型的集合。这同样基于…...
zlib.decompressFile报错 【Bug已解决-鸿蒙开发】
文章目录 项目场景:问题描述原因分析:解决方案:方案1方案2此Bug解决方案总结寄语项目场景: 最近也是遇到了这个问题,看到网上也有人在询问这个问题,本文总结了自己和其他人的解决经验,解决了zlib.decompressFile报错 的问题。 问题: zlib.decompressFile报错,怎么解…...
54.网游逆向分析与插件开发-游戏增加自动化助手接口-项目需求与需求拆解
内容来源于:易道云信息技术研究院VIP课 项目需求: 为游戏增加VIP功能-自动化助手。自动化助手做的是首先要说一下背景,对于授权游戏来讲它往往年限都比较老,老游戏和新游戏设计理念是不同的,比如说老游戏基本上在10年…...
Spring Boot笔记2
3. SpringBoot原理分析 3.1. 起步依赖原理解析 3.1.1. 分析spring-boot-starter-parent 按住Ctrl键,然后点击pom.xml中的spring-boot-starter-parent,跳转到了spring-boot-starter-parent的pom.xml,xml配置如下(只摘抄了部分重…...
MySQL5.7服务器 SQL 模式
官网地址:MySQL :: MySQL 5.7 Reference Manual :: 5.1.10 Server SQL Modes 欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯. MySQL 5.7 参考手册 / ... / 服务器 SQL 模式 5.1.10 服务器 SQL 模式…...
关于LayUI表格重载数据问题
目的 搜索框搜索内容重载数据只显示搜索到的结果 遇到的问题 在layui官方文档里介绍的table属性有data项,但使用下列代码 table.reload(test, {data:data //data为json数据}); 时发现,会会重新调用table.render的url拿到原来的数据,并不会显示出来传…...
MyBatis-mapper.xml配置
1、配置获取添加对象的ID <!-- 配置我们的添加方法,获取到新增加了一个monster对象的iduseGeneratedKeys"true" 意思是需要获取新加对象的主键值keyProperty"monster_id" 表示将获取到的id值赋值给Monster对象的monster_id属性 --><…...
【如何选择Mysql服务器的CPU核数及内存大小】
文章目录 🔊博主介绍🥤本文内容📢文章总结📥博主目标 🔊博主介绍 🌟我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…...
【从浅到深的算法技巧】4.静态方法
1.1.6静态方法 在许多语言中,静态方法被称为函教,静态方法是一组在被调用时会被顺序执行的语句。修饰符static将这类方法和1.2的实例方法区别开来。当讨论两类方法共有的属性时我们会使用不加定语的方法一词。 1.1.6.1静态方法 方法封装了由一系列语句…...
YOLO手部目标检测
手部目标检测原文地址如下:手部关键点检测2:YOLOv5实现手部检测(含训练代码和数据集)_yolov5 关键点检测-CSDN博客 手部检测数据集地址如下: 手部关键点检测1:手部关键点(手部姿势估计)数据集(含下载链接)_手关键点数据集-CSDN博…...
网络IP地址如何更改?怎么使用动态代理IP提高网速?
网络IP地址更改以及使用动态代理IP提高网速的步骤如下: 一、更改IP地址 1. 打开浏览器,输入路由器登陆地址并登陆路由器后台管理界面。 2. 找到“高级设置”或“无线设置”或“VPN设置”一栏,点击“断开”,即可断开网络࿰…...
Flink实时电商数仓之DWS层
需求分析 关键词 统计关键词出现的频率 IK分词 进行分词需要引入IK分词器,使用它时需要引入相关的依赖。它能够将搜索的关键字按照日常的使用习惯进行拆分。比如将苹果iphone 手机,拆分为苹果,iphone, 手机。 <dependency><grou…...
MFC - CArchive/内存之间的序列化应用细节
文章目录 MFC - CArchive/内存之间的序列化应用细节概述笔记END MFC - CArchive/内存之间的序列化应用细节 概述 有个参数文件, 开始直接序列化到文件. 现在优化程序, 不想这个参数文件被用户看到. 想先由参数发布程序(自己用)设置好参数后, 加个密落地. 等用户拿到后, 由程序…...
C语言实验4:指针
目录 一、实验要求 二、实验原理 1. 指针的基本概念 1.1 指针的定义 1.2 取地址运算符(&) 1.3 间接引用运算符(*) 2. 指针的基本操作 2.1 指针的赋值 2.2 空指针 3. 指针和数组 3.1 数组和指针的关系 3.2 指针和数…...
项目——————————
C/C Linux Socket网络编程 TCP 与 UDP_c 语言tcp socket cleint read-CSDN博客C/C Socket - TCP 与 UDP 网络编程_c socket udp-CSDN博客 登录—专业IT笔试面试备考平台_牛客网...
【论文阅读】Realtime multi-person 2d pose estimation using part affinity fields
OpenPose:使用PAF的实时多人2D姿势估计。 code:GitHub - ZheC/Realtime_Multi-Person_Pose_Estimation: Code repo for realtime multi-person pose estimation in CVPR17 (Oral) paper:[1611.08050] Realtime Multi-Person 2D Pose Estima…...
图像分割实战-系列教程9:U2NET显著性检测实战1
🍁🍁🍁图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 U2NET显著性检测实战1 1、任务概述...
RK3568平台 Android13 GKI架构开发方式
一.GKI简介 GKI:Generic Kernel Image 通用内核映像。 Android13 GMS和EDLA认证的一个难点是google强制要求要支持GKI。GKI通用内核映像,是google为了解决内核碎片化的问题,而设计的通过提供统一核心内核并将SoC和板级驱动从核心内核移至可加…...
阿里云服务器节省计划价格便宜_成本优化全解析
阿里云服务器付费模式节省计划怎么收费?为什么说节省计划更节省成本?节省计划是一种折扣权益计划,可以抵扣按量付费实例(不含抢占式实例)的账单。相比包年包月实例,以及预留实例券和按量付费实例的组合&…...
手把手教你用Verilog写一个纯组合逻辑的FP32加法器(附完整代码与避坑指南)
手把手教你用Verilog实现纯组合逻辑FP32加法器(附完整代码与避坑指南) 在数字电路设计中,浮点运算单元一直是性能优化的关键路径。相比时序逻辑实现,纯组合逻辑的FP32加法器能在一个时钟周期内完成所有计算,显著提升吞…...
UE5 GAS调试技巧:巧用ASC的‘Attribute Test’面板,5分钟搞定角色属性配置与验证
UE5 GAS高效调试指南:利用Attribute Test面板快速验证角色属性配置 在虚幻引擎5的游戏开发中,Gameplay Ability System (GAS)作为构建复杂角色能力与属性的核心框架,其调试效率直接影响着RPG类项目的开发进度。本文将深入探讨如何利用Ability…...
企业如何防御LockBit 3.0?从IOC到实战检测规则编写指南
企业级防御实战:LockBit 3.0勒索病毒全维度对抗指南 1. 勒索病毒威胁态势与企业防御挑战 2023年全球网络安全报告显示,勒索软件攻击同比增长47%,其中LockBit系列占比高达28%。不同于传统恶意软件,LockBit 3.0采用模块化设计&#…...
AD5660 16位DAC驱动库深度解析:嵌入式SPI接口实践
1. AD5660 数字模拟转换器库深度解析:面向嵌入式工程师的16位高精度DAC驱动实践1.1 器件本质与工程定位AD5660 是 Analog Devices 推出的单通道、16位电压输出型数模转换器(DAC),采用紧凑的 8 引脚 MSOP 封装,专为对精…...
一、Cisco(静态端口映射实战:从零搭建外网可访问的多服务内网环境)
1. 环境准备与拓扑设计 第一次接触端口映射时,我也被那些专业术语搞得晕头转向。直到自己动手在Cisco Packet Tracer里搭了一套环境,才发现原来原理这么简单。这次我们就用最基础的设备,还原企业里常见的多服务发布场景。 实验设备清单就像搭…...
新手必看!用Python+OpenCV实现简易版视觉里程计(附车道线检测代码)
PythonOpenCV实战:从车道线检测到简易视觉里程计 在自动驾驶和机器人导航领域,视觉里程计(VO)是一项基础而关键的技术。它像是一双"数字眼睛",通过分析连续图像帧之间的变化来估算设备的运动轨迹。想象一下,当你闭着眼…...
WSL 下 Debian 系统 apt 源切换国内镜像的完整指南
1. 为什么需要切换WSL Debian的apt源? 如果你在Windows Subsystem for Linux(WSL)中安装了Debian系统,可能会遇到软件包下载速度慢的问题。这主要是因为默认的软件源服务器位于国外,网络延迟较高。我刚开始用WSL时&…...
Vivado进阶指南:网表物理约束实战解析
1. 网表物理约束的核心价值 第一次接触Vivado的网表物理约束时,我和很多初学者一样困惑:明明RTL代码已经定义了所有功能,为什么还要多此一举?直到在某次高速ADC数据采集项目中,系统频繁出现时序违例,我才真…...
Z-Image-GGUF小程序开发:微信小程序前端调用云端AI绘画API
Z-Image-GGUF小程序开发:微信小程序前端调用云端AI绘画API 最近在折腾AI绘画,发现一个挺有意思的事儿:很多厉害的模型都部署在云端服务器上,但咱们平时用手机的时间可比用电脑多多了。要是能在微信里随手打开一个小程序ÿ…...
SQLite向量检索实战指南:Java开发者的嵌入式AI能力集成落地教程
SQLite向量检索实战指南:Java开发者的嵌入式AI能力集成落地教程 【免费下载链接】sqlite-vec Work-in-progress vector search SQLite extension that runs anywhere. 项目地址: https://gitcode.com/GitHub_Trending/sq/sqlite-vec 一、技术价值:…...
