Java数据类型和位运算

一、数据类型

Java数据类型和位运算_第1张图片

其中基本数据类型为:

Java数据类型和位运算_第2张图片

注意:byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。

其中                                     char 16位  2个字节   

         byte 8位1个字节,  short 16位2个字节 ,  int 32位4个字节 ,  long 64位8个字节

                                                                                   float 32位 4个字节,  double 64位8个字节

声明 long 型常量须后加 ‘l’ 或 ‘L’

二、位运算

1、位运算基本操作

1.1、移位运算符

移位运算符java移位运算符不外乎就这三种:<<(左移)、>>(带符号右移)和>>>(无符号右移)。

1)、 左移运算符

左移的规则只记住一点:丢弃最高位,0补最低位
如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模(取整)。
如对int型移动33位,实际上只移动了33/32=1位。4>>32与4>>0是等价的

当左移的运算数是int 类型时,每移动1位它的第31位就要被移出并且丢弃;
当左移的运算数是long 类型时,每移动1位它的第63位就要被移出并且丢弃。
当左移的运算数是byte 和short类型时,将自动把这些类型扩大为 int 型。(右移也一样)

数学意义
在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方

2)、右移运算符
右移的规则只记住一点:符号位不变,左边补上符号位

按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1
例如,如果要移走的值为负数,每一次右移都在左边补1,如果要移走的值为正数,每一次右移都在左边补0,这叫做符号位扩展(保留符号位)(sign extension ),在进行右移
操作时用来保持负数的符号。

数学意义:右移一位相当于除2,右移n位相当于除以2的n次方。

3)、无符号右移
无符号右移的规则只记住一点:忽略了符号位扩展,0补最高位
无符号右移运算符>>> 只是对32位和64位的值有意义

    @Test
    public void test(){
        // 1、左移( << ):丢弃最高位,0补最低位
        // 0000 0000 0000 0000 0000 0000 0000 0101 然后左移2位后,低位补0://
        // 0000 0000 0000 0000 0000 0000 0001 0100 换算成10进制为20
        System.out.println(5 << 2);// 运行结果是20
        System.out.println(-5 << 2);// 运行结果是-20

        // 2、右移( >> ): 符号位不变,左边补上符号位
        // 0000 0000 0000 0000 0000 0000 0000 1011 然后右移2位,高位补0:
        // 0000 0000 0000 0000 0000 0000 0000 0010
        System.out.println(11 >> 2);// 运行结果是2
        System.out.println(-11 >> 2);// 运行结果是-3

        // 3、无符号右移( >>> ): 忽略了符号位扩展,0补最高位
        // 例如 -5换算成二进制后为:0101 取反加1为1011
        // 1111 1111 1111 1111 1111 1111 1111 1011
        // 我们分别对5进行右移3位、 -5进行右移3位和无符号右移3位:
        System.out.println(5 >> 3);// 结果是0
        System.out.println(-5 >> 3);// 结果是-1
        System.out.println(-5 >>> 3);// 结果是536870911
  }

1.2、位运算符

1、位与( & ):第一个操作数的的第n位于第二个操作数的第n位如果都是1,那么结果的第n为也为1,否则为0。

     11转成二进制是:1011,7转成二进制为:0111。所以结果为:0011

      System.out.println(11 & 7);// 结果为3

2、位或( | ):第一个操作数的的第n位于第二个操作数的第n位 只要有一个是1,那么结果的第n为也为1,否则为0

     11转成二进制是:1011,7转成二进制为:0111。所以结果为:1111

     System.out.println(11 | 7);// 结果为15

3、位异或( ^ ): 第一个操作数的的第n位于第二个操作数的第n位 相反,那么结果的第n为也为1,否则为0

     11转成二进制是:1011,7转成二进制为:0111。所以结果为:1100

      System.out.println(5 ^ 3);//结果为12

4、位非( ~ ):操作数的第n位为1,那么结果的第n位为0,反之。(注:Java中正数的最高位为0,负数最高位为1,即最高位决定正负符)       

    7转成二进制为:0111。所以结果为:1000

    System.out.println(~5);// 结果为-8

2、位运算应用

1.  判断奇偶性,int型变量a是奇数还是偶数   

     (a&1)  = 0 偶数 
     (a&1) =  1 奇数

2.  求平均值,比如有两个int类型变量x、y,首先要求x+y的和,再除以2,但是有可能x+y的结果会超过int的最大表示范围,所以位运算就派上用场啦。
      (x&y)+((x^y)>>1);

 实现原理:我们先了解下面几种情况:
1. 当两个数所有为 1 和为 0 的位都相同时,这两个数的平均值就是 (x & y) 。比如当 x 和 y 都等于 1100 时,x & y 的值也是 1100 ,我们也可以说此时求 x 和 y 的平均数可以用 (x & y) 来求得。
2. 当两个数中的所有对应位有且只有一个为 1 时,那么这两个数的平均值由 (x^y)>>1 表达式求得。比如当 x 为 101100 (十进制 44),y 为 010010 (十进制 18) 时,x ^ y 的值为 111110 ,然后再将 111110 向右移动 1 位后得 11111 (十进制为 31),也就是 (44 + 18)/2 = 31 。
由上面的 情况1 和 情况2 我们知道,将它们两者结合起来便可求得随意两个整数的平均值。

3.  对于一个大于0的整数,判断它是不是2的几次方
    ((x&(x-1))==0)&&(x!=0);

4.  两者数字交换。比如有两个int类型变量x、y,要求两者数字交换,位运算的实现方法:性能绝对高效
    x ^= y;
    y ^= x;
    x ^= y;

5. 求绝对值
    int abs( int x )
   {
     int y ;
     y = x >> 31 ;
    return (x^y)-y ;        //or: (x+y)^y
   }

6.  取模运算,采用位运算实现:
     a % (2^n) 等价于 a & (2^n - 1)

7.  乘法运算   采用位运算实现
     a * (2^n) 等价于 a << n

8.   除法运算转化成位运算
      a / (2^n) 等价于 a>> n

9.   求相反数
      (~x+1)

10  a % 2 等价于 a & 1

你可能感兴趣的:(javaBase)