资讯专栏INFORMATION COLUMN

java移位符浅析

blankyao / 2939人阅读

摘要:左移运算符首先我们将化为源码因为其是类型,所以化为二进制有位正数的补码和反码等于源码的本身。左移运算符是将操作数的二进制码整理左移指定位数,左移后右面空出的位用来补充。补充如果操作类型低于类型,比如,等,先将其转化为类型在进行移位。

java移位符初步使用与简单理解 概述

java移位符主要包括3种:

运算符 名称
>> 左移运算符
<< 有符号右移运算符
<<< 无符号右移运算符

这里我们先附上代码运行实例,原理将在后面以解析下面代码的方式进行讲解:

public class BitOperatorTest {
    public static void main(String[] args){
        System.out.println(1 << 4);
        System.out.println(-1 << 3);
        System.out.println(8 >> 3);
        System.out.println(-8 >> 3);
        System.out.println(-8 >>> 3);
    }
}

结果如下:

16
-8
1
-1
536870911

    首先我们需要清楚在计算机系统中,数值一般用补码来表示,主要原因是因为使用补码可以使符号位和其他位统一处理,我们需要将上面的数值都转化为补码。

左移运算符 1 << 4

    首先我们将1化为源码:0000 0000 0000 0000 0000 0000 0000 0001 (因为其是int类型,所以化为二进制有32位)
    正数的补码和反码等于源码的本身。所以补码也为上述二进制代码。
左移运算符是将操作数的二进制码整理左移指定位数,左移后右面空出的位用0来补充。
左移4位 0000 0000 0000 0000 0000 0000 0000 0001 1*2^0=1
     0000 0000 0000 0000 0000 0000 0000 0001 0000 (红色被移除截断,蓝色是新补的0) 1*2^4=16

-1 << 3

    我们开始第二个输出语句,这是一个负数。负数的反码是他的源码符号位不变,其余按位取反。补码是他的反码加一。
所以我们可以得到-1的源码为1000 0000 0000 0000 0000 0000 0000 0001 -1*2^0=-1
          反码为1111 1111 1111 1111 1111 1111 1111 1110
          补码为1111 1111 1111 1111 1111 1111 1111 1111
   对补码进行操作得111 1111 1111 1111 1111 1111 1111 1111 1000 (红色被移除截断,蓝色是新补的0)
 将结果数转化为源码得1000 0000 0000 0000 0000 0000 0000 1000 -1*2^3=-8

总结

 所以通过上面对左移运算符的简单使用不难发现,我们可以将其简便理解为移动几位,就是为操作数乘以2的几次方。

右移运算符

 左移运算符不牵扯符号位的增补符号位,所以没有有无符号分类

有符号右移运算符 8 >> 3

 根据上面流程,我这里直接就简化为
   源码为:0000 0000 0000 0000 0000 0000 0000 1000 1*2^3=8
   反码为:0000 0000 0000 0000 0000 0000 0000 1000
   补码为:0000 0000 0000 0000 0000 0000 0000 1000
 运算后结果:0000 0000 0000 0000 0000 0000 0000 0001 000 1*2^0=1(红色被移除截断,蓝色是新补的符号位,并且以原来的符号位填补)

-8 >> 3

 根据上面流程,我这里直接就简化为
   源码为:1000 0000 0000 0000 0000 0000 0000 1000 -1*2^3=8
   反码为:1111 1111 1111 1111 1111 1111 1111 0111
   补码为:1111 1111 1111 1111 1111 1111 1111 1000
 运算后结果:1111 1111 1111 1111 1111 1111 1111 1111 000 (红色被移除截断,蓝色是新补的符号位,并且以原来的符号位填补)
转换为源码为:1000 0000 0000 0000 0000 0000 0000 0001 -1*2^0=-1

总结

 同左移运算符一样,总结规律后可得出,右移运算符移动几位则是对操作数除以2的多少次方。

无符号右移运算符 -8 >>> 3

 根据上面流程,我这里直接就简化为
   源码为:1000 0000 0000 0000 0000 0000 0000 1000 -1*2^3=8
   反码为:1111 1111 1111 1111 1111 1111 1111 0111
   补码为:1111 1111 1111 1111 1111 1111 1111 1000
 运算后结果:0001 1111 1111 1111 1111 1111 1111 1111 000 (红色被移除截断,注意黄色部分,在无符号右移运算位中统一补0)
 此时数值将会非常大,所以得到程序中的结果。

补充

 如果操作类型低于int类型,比如byte,char等,先将其转化为int类型在进行移位。
 对于int类型的移位,如果移动位数超过32位,则让位数对32取余,然后进行运行,即a>>33 == a>>1 a>>32 ==a
 同样如果对于long类型的移位,移动位数超过64,则也需要对移动位数进行处理。

代码补充

对于补充内容的代码不进行详解,代码及运算结果如下,基本流程与上面类似,
代码:

public class BitOperatorTest {
    public static void main(String[] args){
        System.out.println((char)4 << 4);
        System.out.println(4 << 4);
        System.out.println(4 << 36);
        System.out.println((long)1214 >> 66);
        System.out.println((long)1214 >> 2);
    }
}

 运行结果:

64
64
64
303
303

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75528.html

相关文章

  • js中表达式 >>> 0 浅析

    摘要:向右被移出的位被丢弃,左侧用填充。因为符号位变成了,所以结果总是非负的。即便右移个比特,结果也是非负的。这些与移位的位数无关,移位位主要就是用了的内部特性做了前两种转换。一个小小的表达式,隐藏着着多重的异常处理。 今天在看lodash的源码中slice这个函数实现的时候发现了里面有这么一行代码 length = start > end ? 0 : ((end - start) >>> ...

    Scliang 评论0 收藏0
  • 结合kmp算法的匹配动画浅析其基本思想

    摘要:写在最前本次分享一下通过实现算法的动画效果来试图展示的基本思路。算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。本次主要通过动画演示的方式展现朴素算法与算法对比过程的异同从而试图理解的基本思路。 写在最前 本次分享一下通过实现kmp算法的动画效果来试图展示kmp的基本思路。 欢迎关注我的博客,不定期更新中—— 前置概念 字符串匹配 字符串匹配是计算...

    wpw 评论0 收藏0
  • HashMap 浅析 —— LeetCode Two Sum 刷题总结

    摘要:注意这里我说的是一般情况下,因为哈希算法需要兼顾性能与准确性,是有一定概率出现重复的情况的。哈希算法实际上是数学家和计算机基础科学家研究的领域。 背景 做了几年 CRUD 工程师,深感自己的计算机基础薄弱,在看了几篇大牛的分享文章之后,发现很多人都是通过刷 LeetCode 来提高自己的算法水平。的确,通过分析解决实际的问题,比自己潜心研究书本效率还是要高一些。 一直以来遇到底层自己无...

    zoomdong 评论0 收藏0
  • java程序入口main()方法浅析

    摘要:程序入口方法浅析方法的方法签名方法签名讲解修饰符类由虚拟机调用,为了没有限制可以自由的调用,所以采用修饰符。返回值主方法被调用,将返回值返回给没有任何意义,因此该方法没有返回值,所以使用。 java程序入口main()方法浅析 main()方法的方法签名 public static void main(String[] args) 方法签名讲解  public修饰符:java类由jav...

    YFan 评论0 收藏0
  • 44个Java代码性能优化总结

    摘要:代码优化的最重要的作用应该是避免未知的错误。此举能够使性能平均提高。抛出异常首先要创建一个新的对象,接口的构造函数调用名为的本地同步方法,方法检查堆栈,收集调用跟踪信息。异常只能用于错误处理,不应该用来控制程序流程。 showImg(https://segmentfault.com/img/remote/1460000015379073); 代码优化的最重要的作用应该是:避免未知的错误...

    YanceyOfficial 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<