写点什么

JAVA 位运算

用户头像
彭阿三
关注
发布于: 2020 年 08 月 13 日

计算机和真实生活中不同,一个数在计算机中只能以二进制(0或者1)的方式表示,现实生活中主要以十进制表示,在二进制的标示中,最高位是符号位,最高位如果为0 ,则表示该数的十进制表示为正数,如果最高位为1,则该数位负数。以十进制3为例,改为8位的二进制,则是[0000 0011],如果是-3转换为8位的二进制是[1000 0011].在这里[0000 0011] 与3表示的意思相同 ,不过[0000 0011] 是机器数,3为真值。



原码, 反码, 补码的基础概念



1. 原码

原码:是最简单的机器数表示法。用最高位表示符号位,‘1’表示负号,‘0’表示正号。其他位存放该数的二进制的绝对值。

若以1000 0010 为例子

  1. 最高位为‘1’,表示这是一个负数,其他七位为‘000 0010’

  2. 即(0*2^7)+(0*2^6)+(0*2^5)+(0*2^4)+(0*2^3)+(0*2^2)+(1*2^1)+(0*2^0)=2(‘^’表示幂运算符)

  3. 所以1000 0010 是-2



2.反码

反码:正数的反码还是等于原码

负数的反码就是他的原码除符号位外,按位取反

若以带符号位的八位二进制数为例:

  1. 3是正数,反码与原码相同,则可以表示为0000 0011

  2. -3的原码是1000 0011,符号位保持不变,低七位(000 0011)按位取反得(100 1100)



3.补码

补码:正数的补码等于他的原码

负数的补码等于反码+1。

(这只是一种算补码的方式,多数书对于补码就是这句话)

前言

日常开发中位运算不是很常用,但是巧妙的使用位运算可以大量减少运行开销,优化算法。举个例子,翻转操作比较常见,比如初始值为1,操作一次变为0,再操作一次变为1。可能的做法是使用三木运算符,判断原始值为1还是0,如果是1,设置为0,否则设置为0.但是使用位运算,不用判断原始值,直接改变值就可以。当然,一条语句可能对代码没什么影响,但是在高重复,大数据量的情况下将会节省很多开销。

位运算符

一些只需要一个操作数的运算符称为一元运算符(或单目运算符)。

二元运算是由两个元素形成第三个元素的一种规则。例如数的加法乘法;更一般地,由两个集合形成第三个集合的产生方法或构成规则称为二次运算。(或双目运算符)

位逻辑运算符

位逻辑运算符包含 4 个:&(与)、|(或)、~(非)和 ^(异或)。除了 ~(即位取反)为单目运算符外,其余都为双目运算符。表 1 中列出了它们的基本用法。



位与运算符

位与运算符为&,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。



例如下面的表达式:100&0

0110 0100 ---> 100

&0000 0000 ---> 0

0000 0000 ---> 0

代码实现:

int x = 100,y = 0;
int z = x&y;
System.out.println("运算结果:"+z);
//运算结果:0



位或运算符

位或运算符为|,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0。



下面是一个使用位或运算符的表达式:4|7

0000 0100--->4

| 0000 0111--->7

0000 0111--->7

代码验证:

int x = 4,y = 7;
int z = x|y;
System.out.println("运算结果:"+z);
//运算结果:7



位异或运算符

位异或运算符为^,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1

下面是一个使用位异或运算符的表达式:4^7



0000 0100--->4

^ 0000 0111--->7

0000 0011--->3

代码验证:

int x = 4,y = 7;
int z = x^y;
System.out.println("运算结果:"+z);
//运算结果:3



位取反运算符

位取反运算符为~,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。

下面是一个使用位取反运算符的表达式: ~5



位移运算符

位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数。表 2 列出了 Java 语言中的两个位移运算符,它们都属于双目运算符。



左位移运算符

左移位运算符为«,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。

例如,将整数 7向左位移 1 位的过程如下:

0000 0111

00000 1110---->14

原来数的所有二进制位都向左移动 1 位。原来位于左边的最高位 0 被移出舍弃,再向尾部追加 0 补位。最终到的结果是14,相当于原来数的 2 倍。



代码验证:

int x = 7;
int z = x <<1;
System.out.println("运算结果:"+z);
//运算结果:14



右位移运算符

右位移运算符为»,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。

例如,将整数 7向右位移 1 位的过程如下:



0000 0111

0000 00111---->3

原来数的所有二进制位都向右移动 1 位。原来位于右边的最低位 1 被移出舍弃,再向最高位追加 0 补位。最终到的结果是 3,相当于原数整除 2 余数舍弃的结果。



复合位赋值运算符

所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式。复合位赋值运算符由赋值运算符与位逻辑运算符和位移运算符组合而成。表 3 列出了组合后的复合位赋值运算符。



int a = 1;
int b = 2;
int c = 3;
a &= 4;
a |= 4;
a ^= c;
a -= 6;
b >>= 1;
c <<= 1;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
a = 1
b = 1
c = 6



注:x<<y 相当于 x*2y ;x>>y相当于x/2y

    从计算速度上讲,移位运算要比算术运算快。





发布于: 2020 年 08 月 13 日阅读数: 73
用户头像

彭阿三

关注

java工程师 2019.06.28 加入

一个慵懒的程序员。

评论

发布
暂无评论
JAVA位运算