Java移位运算原理解析

位运算

引言

最近在为了面试做准备,一直想多了解一些Java底层的运行机制,偶然看到了移位运算符,虽然说在Java这种OOP语言中用的可能没有面向过程语言中用的频繁,但是技多不压身嘛,所以写下了这篇博文将知识分享给大家。

位运算的优点是什么?

位运算的优点就是大大的提高了程序的效率。

什么是位运算?

所有的数据在计算机内存中都是以二进制的形式存在的,通过使用位运算符可以直接操纵二进制数据,而且我们正常的运算符也是通过计算机通过位运算调用栈来实现,所以通过位运算符操纵数据可以节约计算机的内存,同时也大大的提高了程序的效率

都有哪些位运算符

有符号左移 和 右移 <<>>
无符号左移 和 右移 <<<>>>

有符号左移/右移详解

让我们看一下此处的代码

int a  =  12;
int b = a >> 2;  	//有符号右移两位
System.out.println(b);

这里的输出结果是3,原理剖析如下。

移位运算符原理剖析

要想知道这个运算结果是怎么得来的,我们就要探究计算机存储数据的终极奥秘原码、反码和补码。

原码为原数据的直接二进制数的表示。

例如byte类型数据12的原码是00001100
例如byte类型数据-12的原码是10001100

反码,正数的反码和原码相同,负数的反码是除符号位(二进制的第一位表示符号为,0为正1为负)原码按位取反得来的。

例如byte类型数据12的反码是00001100
例如byte类型数据-12的反码是11110011

补码,正数的补码和原码相同,负数的补码是反码+1,补码进行反码+1就是原码。
例如byte类型数据12的补码是00001100
例如byte类型数据-12的补码是11110100

总结,计算机存储数据用的是补码,计算的任何结果都是补码,需要转换骋原码才可以进行进制换算。

我们例子中给出的变量aint类型的,在我第一篇博文《浅谈Java变量和数据类型》
中提到,int类型的数据占用32位储存空间,所以我们变量a的原码一定是32位的二进制数据。
00000000 00000000 00000000 00001100 //12的原码
由于正数的原码、反码、补码都相同,所以可得12的补码是
00000000 00000000 00000000 0000100//12的补码
有符号右移N位,在符号位后自动补N个0(正数)或1(负数 )
0 ==00== 00000000 00000000 00000000 00011//左边的两个0为右移后补全的0
再将此二进制数据转换成十进制的数据,就是我们上面的运算结果3

如果说负数右移两位呢?代码如下

int a = -12;
int b = -12 >> 2;
System.out.println(b);

结果是==-3==
10000000 00000000 00000000 00001100//第一位是符号位。-12的原码
11111111 11111111 11111111 11110011//-12的反码
反码+1求补码
11111111 11111111 11111111 11110100//-12的补码
开始右移,右边末端去掉n位数,因为是有符号,所以默认在符号位后补2个1
11 11111111 11111111 11111111 111101//移动后的-12补码
10 00000000 00000000 00000000 000010//反码
反码+1
10 00000000 00000000 00000000 000011 //结果 -3

左移原理与右移原理相同啦

无符号左移/右移

无符号的移位运算符与有符号的移位运算符原理上大体相同啦,区别就是在有符号移位运算中,我们所补全的数字是取决于符号位(符号位是0就补0,是1就补1),但是在无符号的移位运算中,不管是正数还是负数,都补0。

例如
10000000 00000000 00000000 00001100//第一位是符号位。-12的原码
11111111 11111111 11111111 11110011//-12的反码
反码+1求补码
11111111 11111111 11111111 11110100//-12的补码
开始右移,右边末端去掉n位数,因为是有符号,所以默认在符号位后补2个1
00 11111111 11111111 11111111 111101//移动后的-12补码,同时也是原码,因为是正数
因为第一位是0,表示正数,正数的原码、反码、补码是完全相同的,所以结果用计算机换算得来是1073741821

有的同学可能在这里就产生疑问了
说,你这个-12的补码移位之后不是应该换回原码吗?但是请各位看仔细,因为我是无符号右移,所以我前面默认添了0,这个数就由负数变成正数了,而正数的原码反码补码都相同,所以说结果不用继续换算啦。

左移原理也相同哈

结束语

写于2019.3.19,中软基地。
最大的感受是经过这一系列的培训,对于Java底层原理兴趣越来越浓厚。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值