按位逻辑操作符那些事儿

2024-06-07 13:38
文章标签 逻辑 操作符 按位 事儿

本文主要是介绍按位逻辑操作符那些事儿,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

title: 按位逻辑操作符那些事儿

date: 2017-02-24

tag: java


按位操作符运算符概述

在java底层里面,用到了很多这种符号,不对这些按位逻辑符号弄清楚,不容易看懂jdk源码,这里对按位符号做一个简单的梳理

运算符用法描述
按位与( AND)a & b对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。
按位或(OR)a | b对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。
按位异或(XOR)a ^ b对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。
按位非(NOT)~ a反转操作数的比特位,即0变成1,1变成0。
左移(L)a << ba 的二进制形式向左移 b (< 32) 比特位,右边用0填充。
有符号右移a >> b将 a 的二进制表示向右移b(< 32) 位,丢弃被移出的位。
无符号右移a >>> b将 a 的二进制表示向右移b(< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。

这里注意,java里面没有无符号左移,因为无符号左移<<<和左移<<是一样的概念

按位逻辑操作符

& (按位与)

对每对比特位执行与(AND)操作。只有 a 和 b 都是 1 时,a AND b 才是 1。与操作的真值表如下:

aba AND b
000
010
100
111

上代码:

@Test
public void testAnweiyu(){//按位与,1与0位0,1与1为1,0与0为0int a=14 & 8;toBinaryOutPut(14,"&",8);System.out.println(Integer.toBinaryString(a)+"===="+a);
}
结果:
1110 & 1000
1000====8

| (按位或)

对每一对比特位执行或(OR)操作。如果 a 或 b 为 1,则 a OR b 结果为 1。或操作的真值表:

aba OR b
000
011
101
111
@Test
public void testAnweiHuo(){//按位或,1或0为1,0或0为0,1或1为1int a=14 | 8;toBinaryOutPut(14,"|",8);System.out.println(Integer.toBinaryString(a)+"===="+a);
}
结果
1110 | 1000
1110====14

^ (按位异或)

对每一对比特位执行异或(XOR)操作。当 a 和 b 不相同时,a XOR b 的结果为 1。异或操作真值表:

aba XOR b
000
011
101
110
 @Testpublic void testAnweiYiHuo(){int a=14 ^ 8;toBinaryOutPut(14,"^",8);System.out.println(Integer.toBinaryString(a)+"===="+a);}
结果
1110 ^ 1000
110====6

~ (按位非)

对每一个比特位执行非(NOT)操作。NOT a 结果为 a 的反转(即反码)。非操作的真值表:

aNOT a
01
10
@Test
public void testAnweiFei(){int a=~14;System.out.println(Integer.toBinaryString(14));System.out.println(Integer.toBinaryString(a)+"===="+a);
}
结果
1110
11111111111111111111111111110001====-15

按位移动操作符

<<有符号左移

该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充

在数字 x 上左移 y 比特得到 x * 2y

上代码

@Test
public void testLeftMove(){int a=9<<2;//9左移动2位toBinaryOutPut(9,"<<",2);System.out.println(Integer.toBinaryString(a)+"===="+a);
}
结果:
1001 << 10
100100====36

>>有符号右移

该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。由于新的最左侧的位总是和以前相同,符号位没有被改变。所以被称作“符号传播”。

例如, 9 >> 2 得到 2

@Test
public void testRightMove(){int a=9>>2;//9右边移动2位toBinaryOutPut(9,">>",2);System.out.println(Integer.toBinaryString(a)+"===="+a);
}
结果:
1001 >> 10
10====2

>>>无符号右移

该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(译注:即便右移 0 个比特,结果也是非负的。)

对于非负数,有符号右移和无符号右移总是返回相同的结果。例如, 9 >>> 2 得到 2 和 9 >> 2相同

但是对于负数却不尽相同。 -9 >>> 2 产生 1073741821 这和 -9 >> 2 不同:

上代码:

@Test
public void testNoSignRightMove(){int a=-9>>>2;//9无符号右移动2位toBinaryOutPut(-9,">>>",2);System.out.println(Integer.toBinaryString(a)+"===="+a);
}
结果:
11111111111111111111111111110111 >>> 10
111111111111111111111111111101====1073741821

提问时间如下:

  • 首先负数的二进制为什么是这样的?

    在计算机中,负数以其正值的补码形式表达,将二进制数按位取反,所得的新二进制数称为原二进制数的反码,然后反码+1就是补码了

    例如:9的原码是00000000 00000000 00000000 00001001

    ​ 反码是11111111 11111111 11111111 11110110

    ​ 补码是11111111 11111111 11111111 11110111

    所以-9是这样的

  • int在计算机中存储的是4字节,所以有32位,所以这么长,前面正数是因为把前面的0省略了

  • 那么有符号右移和无符号右移有什么区别呢?

    一个是copy最左侧的位来填充,一个是用0来填充,所以无符号右移总是一个正数

这篇关于按位逻辑操作符那些事儿的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1039334

相关文章

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

逻辑表达式,最小项

目录 得到此图的逻辑电路 1.画出它的真值表 2.根据真值表写出逻辑式 3.画逻辑图 逻辑函数的表示 逻辑表达式 最小项 定义 基本性质 最小项编号 最小项表达式   得到此图的逻辑电路 1.画出它的真值表 这是同或的逻辑式。 2.根据真值表写出逻辑式   3.画逻辑图   有两种画法,1是根据运算优先级非>与>或得到,第二种是采

UMI复现代码运行逻辑全流程(一)——eval_real.py(尚在更新)

一、文件夹功能解析 全文件夹如下 其中,核心文件作用为: diffusion_policy:扩散策略核心文件夹,包含了众多模型及基础库 example:标定及配置文件 scripts/scripts_real:测试脚本文件,区别在于前者倾向于单体运行,后者为整体运行 scripts_slam_pipeline:orb_slam3运行全部文件 umi:核心交互文件夹,作用在于构建真

C++可以被重载的操作符Overloadable operators

C++允许绝大多数操作符被重载,也就是重新定义操作符实现的功能,这样它们的行为可以被设计出来以适应所有的数据类型,包括类。 以下是C++可以被重载的操作符(Overloadable operators): //四则运算符+ - * / %+= -= *= /= %=//比较运算符> >= == != //赋值运算符= //位操作

c++/《重载操作符》

为什么要对运算符进行重载:         C++预定义中的运算符的操作对象只局限于基本的内置数据类型,但是对于我们自定义的类型(类)是没有办法操作的。但是大多时候我们需要对我们定义的类型进行类似的运算,这个时候就需要我们对这么运算符进行重新定义,赋予其新的功能,以满足自身的需求。 <返回类型说明符> operator <运算符符号>(<参数表>) { <函数体> }

【JavaScript】ES6之...延展操作符

… 操作符(也被叫做延展操作符 - spread operator)已经被 ES6 数组 支持。它允许传递数组或者类数组直接做为函数的参数而不用通过apply。      延展操作符一般用于属性的批量赋值上。    通过分析① test8(…args) ②test8(args) ③ test8.apply(null, args) 易看出区别

【Java编程的逻辑】原子变量 CAS 显示锁

原子变量 在理解synchronized中有使用synchronized保证原子更新操作,但是使用synchronized成本太高了,需要先获取锁,最后还要释放锁,如果获取不到锁还需要等到。这些成本都是比较高的,对于这种情况,可以使用原子变量。 Java并发包中的基本原子变量类型有以下几种: AtomicBoolean:原子Boolean类型,常用来在程序中表示一个标志位 AtomicIn

【Java编程的逻辑】容器类的总结

抽象容器类 用法和特点 容器类有两个根接口,分别是Collection 和 Map ,Collection表示单个元素的集合,Map表示键值对的集合 。 Collection Collection表示的数据集合有基本的增、删、查、遍历等方法,但没有定义元素间的顺序或位置,也没有规定是否有重复元素。 List: 是Collection的子接口,表示有顺序或位置的数据集合,增加了根据

【Java编程的逻辑】堆与优先级队列PriorityQueue

完全二叉树 & 满二叉树 & 堆 基本概念 满二叉树是指除了最后一层外,每个节点都有两个孩子,而最后一层都是叶子节点,都没有孩子。 满二叉树一定是完全二叉树,但完全二叉树不要求最后一层是满的,但如果不满,则要求所有节点必须集中在最左边,从左到右是连续的,中间不能有空的。 特点 在完全二叉树中,可以给每个节点一个编号,编号从1开始连续递增,从上到下,从左到右 完全二叉树有一

【Java编程的逻辑】Map和Set

HashMap Map有键和值的概念。一个键映射到一个值,Map按照键存储和访问值,键不能重复。 HashMap实现了Map接口。 基本原理 HashMap的基本实现原理:内部有一个哈希表,即数组table,每个元素table[i]指向一个单向链表,根据键存取值,用键算出hash值,取模得到数组中的索引位置index,然后操作table[index]指向的单向链表。 存取的时候依据键的