zoukankan      html  css  js  c++  java
  • Java Bitwise Operators

    Java中的位操作指定包括:
    ~  按位非(NOT) 
    &  按位与(AND) 
    |  按位或(OR) 
    ^  按位异或(XOR) 
    >>  右移 
    >>>  无符号右移 
    << 左移 

    前面几个都非常简单,主要是移位操作比较容易出错. 
    首先要搞清楚参与运算的数的位数,如int的是32位。long的是64位。 
    如int i = 1; 
    i的二进制原码表示为: 
    00000000000000000000000000000001 
    long l = 1; 
    l的二进制原码表示为: 
    0000000000000000000000000000000000000000000000000000000000000001 
    二、

    正数没有反码、补码,也可以说正数的反码、补码跟原码一样。 
    负数的反码为原码逐位取反, 
    如int i = -1; 
    10000000000000000000000000000001,最高位是符号位。正数为0,负数为1。 
    逐位取反后: 
    01111111111111111111111111111110即反码。 
    反码加1: 
    01111111111111111111111111111111即补码。 
    负数都是用补码参与运算的。得到的也是补码,需要减1取反获得原码。

    三、常用的位运算符--0在位运算中是比较特殊的。

    ^ 异或。 相同为0,相异为1; 任何数与0异或都等于原值。  
    & 与。 全1为1, 有0为0;任何数与0异或都等于0。 
    | 或。 有1为1, 全0为0。任何数与0或都等于原值。 
    <<左移。 补0。 
    >> 右移。 符号位是0补0,是1补1。 
    >>>无符号右移。补0。 
    ~ 非 逐位取反

    四、负数参与的运算,得到的是补码,需要将补码先减1,然后逐位取反,得到原码。即为运算结果。

    0例外,如果得到的是0,则不需减1和取反。 
    另外,两个正数运算后得到的就是原码,不需减1和取反。 
    举例: 
    1^-1, 
    -1 
    10000000000000000000000000000001--原码 
    01111111111111111111111111111110--反码 
    01111111111111111111111111111111--补码 

    00000000000000000000000000000001--原码 
    则1^-1等于 
    01111111111111111111111111111111^ 
    00000000000000000000000000000001= 
    01111111111111111111111111111110--补码 
    01111111111111111111111111111101--反码 
    10000000000000000000000000000010--原码==-2 
    即1^-1=-2 
    举例: 
    1^-2 
    -2 
    10000000000000000000000000000010--原码 
    01111111111111111111111111111101--反码 
    01111111111111111111111111111110--补码 

    00000000000000000000000000000001--原码 
    则1^-2等于 
    01111111111111111111111111111110^ 
    00000000000000000000000000000001= 
    01111111111111111111111111111111--补码 
    01111111111111111111111111111110--反码 
    10000000000000000000000000000001--原码==-1 
    1.<< 
    逻辑左移,右边补0,符号位和其他位一样. 
    正数: 
    x<<1一般相当于2x,但是可能溢出. 
    溢出范围: 230~(231-1) 二进制表示 010000...000到01111....1111,移位后最高为变为1了,变成负数了. 
    负数: 
    x<<1一般也相当于2x,也有可能溢出.所以, x*32可以写成x<<5 
    溢出范围: -231~-(230+1)二进制表示10000...000到101111...1111,移位后最高为变成0了,变成正数了. 
    2.>> 
    算术右移,和上面的不对应,为正数时左边补0,为负数时左边补1. 
    x>>1,相当于x/2,余数被舍弃,因为这个是缩小,所以不会溢出. 
    不过有一点要注意: -1右移多少位都是-1. 
    另外舍弃的余数是正的, 3>>1=1 舍弃的余数是1. 
    -3>>1=-2 舍弃的余数也是1,而不是-1. 
    对于正数 x>>1和x/2相等 
    对于负数 x>>1和x/2不一定相等. 
    3.>>> 
    逻辑右移,这个才是和<<对应的 
    这个把符号位一起移动,左边补0 
    对于正数,>>>和>>是一样的 
    对于负数,右移之后就变成正数了. 
    可以使用Integer.toBinaryString(int i)来看01比特,更加直观. 
    考虑下面的代码: 
    for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; } 
    用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码: 
    for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; } 
    修改后的代码不再做乘以8的操作,而是改用等价的左移3位操作,每左移1位相于乘以2。相应地,右移1位操作相当于除以2。值得一提的是,虽然移位操作速度快,但可能使代码比较难于理解,所以最好加上一些注释。


    无符号右移位操作符“>>>”在将bit串右移位时,从bit串的最左边填充0,这和带符号右移位操作符“>>”不同。“>>”在将bit串右移位时,从bit串的最左边填充原来最左边的位。也就是说,bit串原来最左边的位是符号位,如果为1,则在带符号右移时最左边始终填充1;如果为0,则在带符号右移时最左边始终填充0。

    移位操作符的例子见下表。

    操作 结果 说明
    00110010 << 2 11001000 右边始终填充0
    00110010 >> 2 00001100 结果一样
    00110010 >>> 2 00001100
    10110010 >> 2 11101100 结果不同
    10110010 >>> 2 00101100


    “按位与”操作符“&”对两个bit串按位进行逻辑与,“按位或”操作符“|”对两个bit串按位进行逻辑或,“按位异或”操作符“^”对两个bit串按位进行异或操作。运算规则如下表所示。

    按位与 按位或 按位异或
    0 & 0 = 0 0 | 0 = 0 0 ^ 0 = 0
    0 & 1 = 0 0 | 1 = 1 0 ^ 1 = 1
    1 & 0 = 0 1 | 0 = 1 1 ^ 0 = 1
    1 & 1 = 1 1 | 1 = 1 1 ^ 1 = 0

     “>> 右移,高位补符号位”;
    “>>> 无符号右移,高位补0”;
    “<< 左移”;

    例子:
    -5>>3=-1
    1111 1111 1111 1111 1111 1111 1111 1011
    1111 1111 1111 1111 1111 1111 1111 1111
    其结果与 Math.floor((double)-5/(2*2*2)) 完全相同。

    -5<<3=-40
    1111 1111 1111 1111 1111 1111 1111 1011
    1111 1111 1111 1111 1111 1111 1101 1000
    其结果与 -5*2*2*2 完全相同。

    5>>3=0
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0000
    其结果与 5/(2*2*2) 完全相同。

    5<<3=40
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0010 1000
    其结果与 5*2*2*2 完全相同。

    -5>>>3=536870911 
    1111 1111 1111 1111 1111 1111 1111 1011
    0001 1111 1111 1111 1111 1111 1111 1111

    无论正数、负数,它们的右移、左移、无符号右移 32 位都是其本身,比如 -5<<32=-5、-5>>32=-5、-5>>>32=-5。
    一个有趣的现象是,把 1 左移 31 位再右移 31 位,其结果为 -1。
    0000 0000 0000 0000 0000 0000 0000 0001
    1000 0000 0000 0000 0000 0000 0000 0000
    1111 1111 1111 1111 1111 1111 1111 1111

    位逻辑运算符
    包括:
    & 与;
    | 或;
    ~ 非(也叫做求反);
    ^ 异或

    “& 与”、“| 或”、“~ 非”是基本逻辑运算,由此可以演变出“与非”、“或非”、“与或非”复合逻辑运算。“^ 异或”是一种特殊的逻辑运算,对它求反可以得到“同或”,所以“同或”逻辑也叫“异或非”逻辑。

    例子:
    5&3=1
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0001

    -5&3=1
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0011

    5|3=7
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0111

    -5|3=-5
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0011
    1111 1111 1111 1111 1111 1111 1111 1011

    ~5=-6
    0000 0000 0000 0000 0000 0000 0000 0101
    1111 1111 1111 1111 1111 1111 1111 1010

    ~-5=4
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0100

    5^3=6
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0110

    -5^3=-8
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0011
    1111 1111 1111 1111 1111 1111 1111 1000

  • 相关阅读:
    微信小程序HTTPS
    微信商城-1简介
    va_list
    Event log c++ sample.
    EVENT LOGGING
    Analyze Program Runtime Stack
    unknow table alarmtemp error when drop database (mysql)
    This application has request the Runtime to terminate it in an unusual way.
    How to check if Visual Studio 2005 SP1 is installed
    SetUnhandledExceptionFilter
  • 原文地址:https://www.cnblogs.com/qiengo/p/2507715.html
Copyright © 2011-2022 走看看