Java中的位运算符、移位运算符
1 概述
Java中的位运算符有:&
(与)、|
(或)、^
(异或)、~
(取反)。
移位运算符有:<<
(左移)、>>
(右移)、>>>(无符号右移),没有<<<
运算符。
2 位运算符
计算口诀
运算 | 规则 |
---|---|
& | 全1为1 |
| | 有1为1 |
^ | 相异为1 |
~ | 全部取反 |
2.1 $(与)
有0为0,全1为1
2.2 |(或)
有1为1,全0为0
2.3 ^(异或)
相同为0,相异为1
2.4 ~(非)
0变1,1变0
3 移位运算
在阅读源码的过程中,经常会看到这些符号<< ,>>,>>>,这些符号在Java中叫移位运算符,在写代码的过程中,虽然我们基本上不会去写这些符号,但需要明白这些符号的运算原理,比如HashMap中有以下代码:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//1左移4位为16
static final int MAXIMUM_CAPACITY = 1 << 30;//1左移30位为1073741824
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//无符号右移
}
上段代码中就包含左移运算符<<,无符号右移运算符>>>。
接下来我们以Java中的int类型为例介绍三种移位运算符。
首先定义int类型的变量a,b
int a = 0B00101100_01010011_01101000_11010110; //十进制743663830
int b = 0B10101100_01010011_01101000_11010110; //十进制-1403819818
3.1 左移运算符:<<
左移运算符<<
的操作是舍弃高位,低位补0.
如图是int类型a在左移1位和2位后的结果。
可以看到左移1位的值是原始值的两倍,所以可以用左移代理乘2的倍数运算。但是如果左移后的值超出了类型的最大值,结果就不可预知了,可能会变成负数,也可能比原来的值小。如图,变量a在左移两位后最高位变为了1,值就变为了负值。
程序中的写法:
public class TestDemo {
public static void main(String[] args) {
int b = 0B10101100_01010011_01101000_11010110;
int a = 0B00101100_01010011_01101000_11010110;
System.out.println("a的原始十进制:\t"+a);
System.out.println("a的原始二进制:\t"+getBinaryString(a));
System.out.println("a的左移1位二进制:\t"+getBinaryString(a<<1));
System.out.println("a的左移1位十进制:\t"+getInt(getBinaryString(a<<1)));
System.out.println("a的左移2位二进制:\t"+getBinaryString(a<<2));
System.out.println("a的左移2位十进制:\t"+getInt(getBinaryString(a<<2)));
}
static String getBinaryString(int a){
String binaryString = Integer.toBinaryString(a);//转成二进制
String zeroString = "";//补缺少的0
for (int i=0;i<32 - binaryString.length();i++){
zeroString += "0";
}
binaryString = zeroString + binaryString; //补上0的二进制
String regex = "(.{8})";
binaryString = binaryString.replaceAll(regex,"$1_");
binaryString = binaryString.substring(0,binaryString.length() - 1);
return binaryString;
}
static int getInt(String a ){
a = a.replace("_","");
char first = a.charAt(0);
a = a.substring(1);
int value = Integer.parseInt(a,2);
return first == '0' ? value:-value;
}
}
a的原始十进制: 743663830
a的原始二进制: 00101100_01010011_01101000_11010110
a的左移1位二进制:01011000_10100110_11010001_10101100
a的左移1位十进制:1487327660
a的左移2位二进制:10110001_01001101_10100011_01011000
a的左移2位十进制:-827171672
如果移动的位数大于等于类型本身的位数,会对移动的位数求余后再移动。
如 a<<40,是左移40位,大于int类型的32位,实际应该左移40%32=8位。
System.out.println("a左移8位:\t"+(a<<8));
System.out.println("a左移40位:\t"+(a<<40));
a左移8位: 1399379456
a左移40位: 1399379456
可以看到左移8位和左移40位,结果是相同的。
由于double,float在二进制中的表现比较特殊,因此不能来进行移位操作,报错,编译不过,如下图:
注意:其它几种整形byte,short移位前会先转换为int类型(32位)再进行移位,这里就不写代码测试了,大家有兴趣可自行测试。
3.2 右移运算符:>>
左移运算符>>
的操作是舍弃低位,高位补符号位.
如图是int类型a在右移1位和2位后的结果。
可以看到右移1位的值是原始值的1/2,所以可以用右移代替除2运算。和左移一样,int类型移位大于等于32位时,long类型大于等于64位时,会先做求余处理再位移处理,byte,short移位前会先转换为int类型(32位)再进行移位。以上是正数的位移,我们再来看看负数的右移运算,如图,
综上所述:右移运算符>>的运算规则也很简单,丢弃右边指定位数,左边补上符号位。
3.3 无符号右移运算符:>>>
无符号右移运算符>>>和右移运算符>>是一样的,只不过右移时左边是补上符号位,而无符号右移运算符是补上0,也就是说,对于正数移位来说等同于:>>,负数通过此移位运算符能移位成正数。
无符号右移运算符>>的运算规则也很简单,丢弃右边指定位数,左边补上0。
参考:Java中的移位运算符
Java中的位运算符、移位运算符的更多相关文章
- Java中的位掩码BitMask
目录 JDK源码的使用 日常工作中的使用 JDK源码的使用 最近在JDK源码中闲逛,无意中看到了java.lang.reflect.Modifier这个类,这个类很简单,都是些常量定义和判断方法,于是 ...
- Java中的位运算符、移位运算
一.位运算 Java中有4个位运算,它们的运算规则如下: (1)按位与 (&) :两位全为1,结果为1,否则为0: (2)按位或 (|) :两位有一个为1,结果为1,否则为0: (3) ...
- Java中的位运算符
Java提供的位运算符有:左移( << ).右移( >> ) .无符号右移( >>> ) .位与( & ) .位或( | ).位非( ~ ).位异或( ...
- Java中的位运算符 &、|、^、~、<< 和 >>
一.& 按位与运算符 5 & 3 = 1 5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101 3转换为二进制:0000 0000 0000 ...
- java中的位运算及移位运算
为了方便对二进制位进行操作,Java给我们提供了以下四个二进制位操作符: & 按位与 | 按位或 ^ 按位异或 ~ 按位取反 Java中有三个移位运算符: 左移:&l ...
- java中的7个位运算运算符
位运算指的是针对整数的二进制进行的位移操作. 位运算提供比算术运算更高的效率,但是位运算的代码可读性较差,建议所有使用位运算的地方写上注释. Java中提供7个位运算符用于位运算. 左移(<&l ...
- java中的、标识符、运算符以及数据类型之间的转换。
---恢复内容开始--- 数据类型之间的转换: 1:自动转换:就是不用说出要转换成什么类型,由java中的虚拟机自动将小数据类型转换成大数据类型,但大数据中的数据精度有可能被破坏. 2:强制转换:强制 ...
- Java中关于位运算的面试题
位运算的效率是最高的,因为位位运算是直接对二进制进行操作 位运算只能应用于整型和char类型(char类型可以看做是特殊的无符号的整形) 面试题: a: 判断一个数是否是奇数 a & 1 == ...
- Java中的位运算及简单的算法应用介绍
众所周知,计算机底层是二进制.而java作为一门计算机编程语言,也对二进制的位运算提供了完整的支持. 在java中,int是32位的,也就是说可以用来实现32位的位运算.方便起见,我们一般用16进制对 ...
- JAVA中自增自减运算符(i++与++i的区别)
注意: 自增运算符和自减运算符只能用于变量,而不能用于常亮或表达式 运算符 运算 范例 结果 ++ 自增(前):先运算后取值 a=2;b=++a; a=3;b=3; ++ 自增(后):先取值后运算 a ...
随机推荐
- 使用Docker编译安装运行Doris
一.编译源码 (1)拉取编译镜像docker pull apache/incubator-doris:build-env-1.2 (2)Mac电脑上拉取源码git clone https://gith ...
- Luogu P4287 SHOI2011 双倍回文 题解 [ 紫 ] [ manacher ]
双倍回文:回文子串结论的经典应用. 结论 先放本题最关键的结论:一个字符串本质不同的回文子串最多只有 \(n\) 个. 考虑如何证明: 假设我们一个一个地在当前字符串(黑色部分)的结尾加入字符(红色部 ...
- 解密prompt系列49. 回顾R1之前的思维链发展路线
在所有人都在谈论R1的今天,作为算法也是有些千头万绪无从抓起.所以这一章先复盘,我先按照自己的思路来梳理下R1之前整个模型思维链的发展过程.下一章再展望主要去看RL在Agent上的一些尝试,毕竟Age ...
- SpringBoot - [07] Web入门
题记部分 一.Web 入门 SpringBoot将传统Web开发的mvc.json.tomcat等框架整合,提供了spring-boot-starter-web组件,简化了Web应用配置.创建Sp ...
- faker 函数支持哪些
3.2 常用函数 除了上述介绍的fake.name和fake.address生成姓名和地址两个函数外,常用的faker函数按类别划分有如下一些常用方法. 1.地理信息类 fake.city_suffi ...
- nginx 根据 URL 参数引入不同的文件
同步发布:https://blog.jijian.link/2020-06-30/nginx-import-file/ 编程世界中各种奇奇怪怪的需求都有,本次遇到一个需求:根据URL参数判断,包含 x ...
- Django实战项目-学习任务系统-用户管理
接着上期代码框架,开发第6个功能,用户管理,查看用户信息和学生用户属性值,尤其是总积分值,还可以查看积分流水明细,完成任务奖励积分,兑换物品消耗积分. 第一步:编写第6个功能-用户管理 1,编辑模型文 ...
- 系统自带模版在 emlog pro 1.8.0 底部信息错位问题暂时的解决方案
问题描述 作为一名 emlog 爱好者,笔者闲暇时间经常为 emlog 系统的 Github 仓库里( https://github.com/emlog/emlog )提 pr 和修修补补,就像其他知 ...
- 物理机Jenkins接入K8s环境
前言 本次记录物理机部署Jenkins,k8s弹性伸缩agent节点供部署项目. 安装 K8S 插件 登录 Jenkins,系统管理→ 插件管理 → 搜索 kubernetes,选择第二个 Kuber ...
- ASP.NET Session 清除
// 值为 null,这样对应的 Session 会继续存在,但值为 null Session["UserId"] = null; // 移除指定 Session Session. ...