java的位运算符(>>,<<,>>>,&,|)

转载 2016年08月29日 12:23:42

主要总结下java的位运算符的操作。java的位运算符不紧可以提高运行效率,同时也有会意想不到的效果(java.util.ArrayDeque有很好的体现)。

开始说位运算符之前,先简单的复习下补码的知识,然后举个简单的例子说明下计算机中的补码操作(计算机中的加减法)。

补码

计算机进行加减法操作时,都是以补码进行操作的,所以java中的位运算都是以补码进行操作的。正数的补码是其本身,而负数的补码为其反码+1。如下例子。

因为java中int型是4个字节,需要32位,为了写起来和看起来更加直观,这里使用8位来进行模拟。

对于正数2 ,其二进制形式为00000010,其补码也为00000010。

对于负数-2,其二进制形式为10000010,其补码为11111110。

为什么计算机会用补码进行操作,我用十进制来模拟一下。举两个数,一个是a=9145,一个是b=0645。(第一位为符号位,9表示负数,0表示正数)

对于二进制来说,1取反为0,因为1+0=1(比2小1);对于十进制来说,1取反为8,因为1+8=9(比10小1);对于16进制来说,1取反为14,因为1+14=15(比16小1);

所以对于十进制a=9155,他的反码为9854,而其补码为9855(反码+1),对于b,因为是正数,所以补码跟原码一样。所以a+b(补码相加)=9855+0645=10500。因为我们都是四位正数进行相加,所以10500的第一位就要舍去,得到的结果为0500。而0代表的是正数,所以结果就是500;

再举一个例子 比如 a=9645,b=0145(第一位为符号位,9表示负数,0表示正数)

a的补码为9355,b的补码跟原码一样。a+b=9355+0145=9500。所以结果就是-500。

计算机为什么要用补码运算呢,而不是用原码,因为计算机不像人一样,他不会进行减法运算,只是通过一种方式将减法变成了加法运算,也就是所谓的补码。

java的位操作

介绍完了补码,接下来介绍java的位操作(通过补码来进行操作)。

例1 右移操作

5>>1,-5>>1; 结果分别为2,-3;

先分析5>>1,因为5的补码为00000101。右移一位以后为00000010(结果为补码),再求其原码(跟补码一样),结果为2。因为5是正数,所以最高位补0,

再分析-5>>1,因为-5的补码为11111011。右移一位以后为11111101(结果为补码),在求其原码,结果为10000011,转换成十进制为-3。因为-5是负数,所以最高位补1。

例2 无符号右移

5>>>1,-5>>>1;结果分别为2,2147483645

在例1右移操作中,正数移动时,最高位补0,而负数移动时,最高位补1,而对于无符号右移,不管是正数还是负数,移动时最高位都会补0;

5>>>1和例1中类似,直接分析-5>>>1。-5的补码为11111011,无符号右移一位后为01111101,再求其原码(移动后变成了正数,所以原码和补码一致)最后结果为2147483645。

例3 &操作

5&7,5&-7,-5&-7。结果为5,1,-7。

先分析5&7,因为5的补码为00000101,7的补码为00000111;所以两个相与后为00000101,即为5。(&操作即每一位进行操作,都是1的话结果为1)

再分析5&-7,5的补码为00000101,-7的补码为11111001。所以两个相与后为00000001(因为是正数,其原码与补码一致),转换成十进制为1。

再分析-5&-7,-5的补码为11111011,-7的补码为11111001,两个相与后为11111001,因为是负数,所以再求其原码,为10000111,结果为-7。

java的 ’<<‘ 和 ’|‘ 操作与 ’>>‘ 和 ’&‘ 类似,就不在举例说明。

java位操作在JDK中的应用

在java.util包中有一个ArrayDeque类来实现队列的操作。ArrayDeque类中维护了一个E[] elements数组来存储对象。

ArrayDeque类提供了不同的构造方法,其中有一个构造方法可以用来定义elements数组的大小,如下:

 public ArrayDeque(int numElements) {
        allocateElements(numElements);
    }

   private void allocateElements(int numElements) {
        int initialCapacity = MIN_INITIAL_CAPACITY;
        // Find the best power of two to hold elements.
        // Tests "<=" because arrays aren't kept full.
        if (numElements >= initialCapacity) {
            initialCapacity = numElements;
            initialCapacity |= (initialCapacity >>>  1);
            initialCapacity |= (initialCapacity >>>  2);
            initialCapacity |= (initialCapacity >>>  4);
            initialCapacity |= (initialCapacity >>>  8);
            initialCapacity |= (initialCapacity >>> 16);
            initialCapacity++;

            if (initialCapacity < 0)   // Too many elements, must back off
                initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
        }
        elements = (E[]) new Object[initialCapacity];
    }

其中在allocateElements方法中,经过一系列的操作来初试化elements的大小。例如你给个初试化大小为6,经过allocateElements方法后,大小就变了8,。如果是14.则最后的elements的大小为16。最后不论怎样,都会变成2的N次方。
最后主要是说下ArrayDeque的进队和出队。在ArrayDeque类中维护了两个变量,分别是head和tail。分别指向第一个进队的元素和最后一个进队的元素。

如下为入队的方法

 public boolean add(E e) {
        addLast(e);
        return true;
    }

    public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity(); 
    }

接下的代码为出队的操作

public E pop() {
        return removeFirst();
    }

    public E removeFirst() {
        E x = pollFirst();
        if (x == null)
            throw new NoSuchElementException();
        return x;
    }

浅谈我对Java位运算符的了解

在JAVA程序里,支持位运算。 已知位运算有7种, —— 请看如下图。 左移运算,往左移动多少位,就是乘以2的多少位次幂。 特点:往左边移动,就是乘以。移动后的值,比原来的值大。 ...
  • xoptimal
  • xoptimal
  • 2014年12月22日 21:21
  • 309

Java位运算符使用方法

package test; /** * ^的运算方法是 相同为0,相反为1 * |的运算方法是 有1则为1 * &的运算方式是 有0则为0 * ~的运算方法是 求反,负数的二进制...
  • phoenix2121
  • phoenix2121
  • 2010年07月28日 18:08
  • 3819

Java中的位运算符(操作数只能是整型和字符型数据)

java中的位运算符有:左移(>)、无符号右移(>>>)、位与(&)、位或(|)、位非(~)、位异或(^),除位异或是一元操作符外,都是二元操作符。 (位运算的实质都是先将十进制数转化为二进制在进行...
  • set_one_name
  • set_one_name
  • 2017年08月08日 13:56
  • 351

Java位运算原理及使用讲解

前言 日常开发中位运算不是很常用,但是巧妙的使用位运算可以大量减少运行开销,优化算法。举个例子,翻转操作比较常见,比如初始值为1,操作一次变为0,再操作一次变为1。可能的做法是使用三木运算符,判断原始...
  • Goskalrie
  • Goskalrie
  • 2016年10月12日 14:12
  • 10127

位运算符的一些用途

 虽然平时很少用到位运算符,但是在某些时候,这些小东西确实能够给我们提供很好的解决方案。 概述位运算是对二进制数进行运算。java中的位运算符有[&, |, ^, ~, >, >>>],其中[~]是一...
  • superbeck
  • superbeck
  • 2010年03月17日 08:32
  • 8458

位运算符经典算法

1.请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如把 9 表示成二进制是 1001;有 2 位是 1,因此如果输入 9,函数输出 2. public static int ...
  • qq_26803795
  • qq_26803795
  • 2018年01月23日 16:40
  • 26

java 的位运算符详解实例 ------与(&) 、或( |) 、非( ~) 、异或( ^)

位运算符主要针对二进制,它包括了:“与”、“非”、“或”、“异或”。从表面上看似乎有点像逻辑运算符,但逻辑运算符是针对两个关系运算符来进行逻辑运算,而位运算符主要针对两个二进制数的位进行逻辑运算。下面...
  • guoanddong
  • guoanddong
  • 2016年09月24日 16:40
  • 316

Java笔试题分类总结--位操作

位操作优点:在计算机中所有数据都是以二进制的形式储存的。 位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快。位操作基础:基本的位操作符有"与"、"或"、"异或"、"取反"、"...
  • daidaineteasy
  • daidaineteasy
  • 2016年04月07日 15:22
  • 1016

&和&&的区别,逻辑运算符和位运算符

&:按位操作符(“与”),将两个表达式的值按二进制位展开,对应的位(bit)按值进行”与”运算,结果保留在该位上。 eg1:17&18 对应的二进制就是00010010             ...
  • zhangzhangliyin
  • zhangzhangliyin
  • 2016年05月08日 11:43
  • 4075

C语言位运算符及常见用法

一、位运算符C语言提供了六种位运算符: & 按位与 | 按位或 ^ 按位异或 ~ 取反 >> 右移 1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有...
  • xing_hao
  • xing_hao
  • 2011年08月11日 09:46
  • 29033
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java的位运算符(>>,<<,>>>,&,|)
举报原因:
原因补充:

(最多只允许输入30个字)