zoukankan      html  css  js  c++  java
  • java位移运算符3 转

    https://www.cnblogs.com/winsker/p/6728672.html

    移位运算符操作的对象就是二进制的位,可以单独用移位运算符来处理int型整数。

    理解java移位运算符
    运算符 含义 例子
    << 左移运算符,将运算符左边的对象向左移动运算符右边指定的位数(在低位补0) x<<3
    >> "有符号"右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1. x>>3
    >>> "无符号"右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制,也就是说,无论值的正负,都在高位补0. x>>>3

    以int类型的6297为例,代码如下:

    1 System.out.println(Integer.toBinaryString(6297));   
    2 System.out.println(Integer.toBinaryString(-6297));   
    3 System.out.println(Integer.toBinaryString(6297>>5));   
    4 System.out.println(Integer.toBinaryString(-6297>>5));   
    5 System.out.println(Integer.toBinaryString(6297>>>5));   
    6 System.out.println(Integer.toBinaryString(-6297>>>5));   
    7 System.out.println(Integer.toBinaryString(6297<<5));   
    8 System.out.println(Integer.toBinaryString(-6297<<5));  

    运行结果:

    1100010011001

    11111111111111111110011101100111
    11000100
    11111111111111111111111100111011
    11000100
    111111111111111111100111011
    110001001100100000
    11111111111111001110110011100000

    注:x<<y 相当于 x*2;x>>y相当于x/2y
        从计算速度上讲,移位运算要比算术运算快。
        如果x是负数,那么x>>>3没有什么算术意义,只有逻辑意义。

    结果分析:

    位数:

    00000000 00000000 00000000 00000000

    6297
    00000000 00000000 00011000 10011001
    -6297
    10000000 00000000 00011000 10011001   源码
    11111111  11111111   11100111   01100110  反码 除符号位按位取反

    11111111  11111111   11100111   01100111   补码 除符号位反码加1

    6297>>5

    00000000 00000000 00000000 11000100 <右移5位后>

    -6297>>5

    11111111 11111111 11100111 01100111 补码<十进制负数在计算机中二进制表示形式>

    11111111 11111111 11111111  00111011 <右移5位后>

    6297>>>5

    00000000 00000000 00011000 10011001

    00000000 00000000 00000000 11000100 <右移5位后>

    -6297>>>5

    11111111 11111111 11100111 01100111 补码<十进制负数在计算机中二进制表示形式>

    0000011 11111111 111111111 00111011 <逻辑右移5位后> 存疑

    6297<<5

    00000000 00000000 00011000 10011001

    00000000 00000011 00010011 00100000

    -6297<<5

    11111111  11111111   11100111   01100111   补码 除符号位反码加1<计算机中负数的存在形式>

    11111111  11111100  11101100   11100000  <左移五位后>

    =======================================================================

    首先,移位操作符能操作的数只有int类型和long类型,这个是指左操作数的类型。对于int类型而言,int在Java中占4字节,一共32位,也就是说,对于一个在Java中的int数据,做32次移位,那么这个int数据就完全变了,以左移为例,左移是补0,那么对于任意一个int类型数据,做32次移位,那么int数据变成32位全0的数据,Java不允许一次性移位左操作数的所有位,也就是右操作数不能大于32。于是回到上述的句子,其指的是右操作数的低5位,5位二进制所代表的最大值为2^5-1,为31,所以取右操作数的低5位,就是只看右操作数的二进制的低5位,其数值不会超过2^5次方,也就是int的32位。因此,移位操作符进行移位的实际次数,其实是右操作数2的次数。

    5位二进制所代表的最大值为2^5-1(注:2^5-1 -->32-1 = 31),为31
    位数
    0  0  0  0  0
    每位的值
    16 8  4  2  1
    推测1:01111 -->15
    推测2: 11111 -->31<无符号位>

    对上面那段话的理解是:移位操作符操作的运算对象是二进制的“位”,int类型是32位也就是2的5次幂 !如果移32位以上,那么原来的数的信息会全部丢失,这样也就没有什么意义了!所以上面的“只有右侧的5个低位才会有用”说的是:移位操作符右端的那个数(化成二进制)的低5位才有用,即
    X < <y;

    是指y的低5位才有用,即不能大于32。 而对于long型也是同样的道理!

    因此,如果对一个int 型,进行移位,X < <y; 当y小于32时,移位后的结果一般都在我们的预料当中;而如果y大于32时,由于移位超出了int所能表示的范围,这时就先把y化成二进制数,然后取该二进制数右端的低5位,再把这5位化成十进制,此时的这个十进制就是要对X移动的位数。

    例如:

    int int a=140;
    a << 34
    System.out.println(Integer.toBinaryString(a << b));

    上面那两个语句的执行过程是:先把a化成二进制数:10001100

    执行语句 a << 34 对a左移32位时,先把 34化成二进制:100010,对该二进制数取右边5位,即00010,化成十进制数为2,所以实际上是对a左移两位。现在,地球人都会知道上面程序的输出结果是:1000110000

    //////////////////////////////////////////////////

    移位运算符和按位运算符一样,同属于位运算符,因此移位运算符的位指的也是二进制位。它包括以下几种:
    左移位(<<):将操作符左侧的操作数向左移动操作符右侧指定的位数 。移动的规则是在二进制的低位补0。

    有符号右移位(>>):将操作符左侧的操作数向右移动操作符右侧指定的位数。移动的规则是,如果被操作数的符号为正,则在二进制的高位补0;如果被操作数的符号为负,则在二进制的高位补1。

    无符号右移位(>>>):将操作符左侧的操作数向右移动操作符右侧指定的位数。移动的规则是,无论被操作数的符号是正是负,都在二进制位的高位补0。
    注意,移位运算符不存在“无符号左移位(<<<)”一说。与按位运算符一样,移位运算符可以用于byte、short、int、long等整数类型,和字符串类型char,但是不能用于浮点数类型float、double;当然,在Java5.0及以上版本中,移位运算符还可用于byte、short、int、long、char对应的包装器类。我们可以参照按位运算符的示例写一个测试程序来验证,这里就不再举例了。
    与按位运算符不同的是,移位运算符不存在短路不短路的问题。
    写到这里就不得不提及一个在面试题中经常被考到的题目:

    请用最有效率的方法计算出2乘以8等于几?这里所谓的最有效率,实际上就是通过最少、最简单的运算得出想要的结果,而移位是计算机中相当基础的运算了,用它来实现准没错了。左移位“<<”把被操作数每向左移动一位,效果等同于将被操作数乘以2,而2*8=(2*2*2*2),就是把2向左移位3次。因此最有效率的计算2乘以8的方法就是“2<<3”。

    最后,我们再来考虑一种情况,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,结果会是怎样呢?比如,1<<35=?呢?
    这里就涉及到移位运算的另外一些规则:
    byte、short、char在做移位运算之前,会被自动转换为int类型,然后再进行运算。 byte、short、int、char类型的数据经过移位运算后结果都为int型。 long经过移位运算后结果为long型。

    在左移位(<<)运算时,如果要移位的位数大于被操作数对应数据类型所能表示的最大位数,那么先将要求移位数对该类型所能表示的最大位数求余后,再将被操作数移位所得余数对应的数值,效果不变。

    比如1<<35=1<<(35%32)=1<<3=8。 对于有符号右移位(>>)运算和无符号右移位(>>>)运算,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,那么先将要求移位数对该类型所能表示的最大位数求余后,再将被操作数移位所得余数对应的数值,效果不变。。

    比如100>>35=100>>(35%32)=100>>3=12。

    另:

    Java 的 Integer.toBinaryString 方法

    public static String toBinaryString(int i)
    
        //以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式。 
        //如果参数为负,该无符号整数值为参数加上 2^32;否则等于该参数。
    
            System.out.println(Integer.toBinaryString(-1)) ;
            System.out.println(Integer.toBinaryString(-2)) ;
            System.out.println(Integer.toBinaryString(1)) ;
    输出:
            11111111111111111111111111111111
            11111111111111111111111111111110
            1
    

    结论输出的是数字的二进制补码。为什么说是以 二进制无符号整数形式 返回一个 整数类型的字符串,为什么 如果参数为负数,就要加上 232 次方?

    因为Java里的int是有符号的,在内存中没有正负之分,只有0/1,整数是用补码表示的

    正数补码等于原码
    负数的补码等于其绝对值的反码+1,正好等于自身+2^32(对于4字节的整型来说)

    -1 的补码 就是 绝对值1 的反码(按位取反) 11111111 11111111 11111111 11111110 再+1
    等于 11111111 11111111 11111111 11111111

    这样正好能把最高位为1的数字用来表示负数,而最高位为0的数字表示非负数

    10000000 00000000 00000000 00000000 => -2147483648
    11111111 11111111 11111111 11111111 => -1
    00000000 00000000 00000000 00000000 => 0
    00000000 00000000 00000000 00000001 => 1
    01111111 11111111 11111111 11111111 => 2147483647
    

    因此负数+2^32之后的二进制串,就是该负数内存中准确的存储形式

      

                   

  • 相关阅读:
    Delphi公用函数单元
    Delphi XE5 for Android (十一)
    Delphi XE5 for Android (十)
    Delphi XE5 for Android (九)
    Delphi XE5 for Android (八)
    Delphi XE5 for Android (七)
    Delphi XE5 for Android (五)
    Delphi XE5 for Android (四)
    Delphi XE5 for Android (三)
    Delphi XE5 for Android (二)
  • 原文地址:https://www.cnblogs.com/cici-new/p/10498063.html
Copyright © 2011-2022 走看看