java 位运算



java 位运算实例源码,按位与 &运算,按位或 |运算:

public class BitOperate {

public static void bitCalc() {
byte a = 12,b=10;
byte c = -12,d=-10;

/**
* 1、java按位与 &
* (AND)
* 运算方法:当两边操作数的位同时为1时,结果为1,否则为0
*
* 注意:符号位也会参与运算
*/
// 12二进制表示(1100),10二机制(1010)
System.out.println(“正数与运算:”+(a&b)); //1100&1010=1000 == 8
//注意:负数计算机用补码表示:
// -12:11110100, -10:11110110
System.out.println(“负数与运算:”+(c&d)); //(11110100)补=(10001100)原 == -12
//
System.out.println(“正负数与运算:”+(a&d));//00001100&11110110 = 00000100 == 4
System.out.println();

/**
* 2、java按位或 |
* (OR)
* 运算方法:当两边操作数的位有一边为1时,结果为1,否则为0
*
*/
System.out.println(“正数或运算:”+(a|b)); //1100|1010=1110 == 14
// -12:11110100, -10:11110110
System.out.println(“负数或运算:”+(c|d)); //(11110110)补=(10001010)原 == -10
// 12:00001100, -10:11110110
System.out.println(“正负数或运算:”+(a|d)); //(11111110)补=(10000010)原 == -2
System.out.println();

/**
* 3、java按位非 ~
* (NOT)
* 运算方法:操作数的位0变1,1变0
*
*/
// 12: 00001100
System.out.println(“正数非运算:”+ (~a)); //11110011=(10001101)原 == -13
// -12: 11110100
System.out.println(“负数非运算:”+ (~c)); //00001011 == 11
System.out.println();

/**
* 4、java按位异或 ^
* (XOR)
* 运算方法: 对比每个数位上的0或1如果相同,那么结果就取0,如果不同就取1
*
*/
// 12: 00001100), 10: 00001010)
System.out.println(“正数异或运算:”+ (a^b)); //000000110 == 6
// -12:11110100, -10:11110110
System.out.println(“负数异或运算:”+(c^d)); //00000010 == 2
// 12:00001100, -10:11110110
System.out.println(“正负数异或运算:”+(a^d)); //(11111010)补=(10000110)原 == -6
System.out.println(“——————————————–”);

/**
* 移位运算
*
* 概念:
* 移位运算符就是在二进制的基础上对数字进行平移。
*
* 分类:
* 按照平移的方向和填充数字的规则分为三种:<<(左移)、>>(带符号右移)和>>>(无符号右移)。
*
* 运算方式:
* 在移位运算时,byte、short和char类型移位后的结果会变成int类型,
* 对于byte、short、char和int进行移位时,规定实际移动的次数是移动次数和32的余数,
* 也就是移位33次和移位1次得到的结果相同。
* 移动long型的数值时,规定实际移动的次数是移动次数和64的余数,
* 也就是移动66次和移动2次得到的结果相同。
*
*
*/

/**
* 5、java左移 <<
*
* 运算方法:
* 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
*
* 数学意义:
* 在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方。
*
*/
//before: 0000 0000 0000 0000 0000 0000 0000 1100
//after: 0000 0000 0000 0000 0000 0000 0011 0000 == 48
System.out.println(“正数左移:”+(a<<2)); //a*2*2 = 48
System.out.println(“负数左移:”+(c<<2)); //c*2*2 = -48
//数字溢出的情况:
//12
//before: 0000 0000 0000 0000 0000 0000 0000 1100
//<<28 after : 1100 0000 0000 0000 0000 0000 0000 0000
//<<29 after : 1000 0000 0000 0000 0000 0000 0000 0000 -0补码代表最小负数2的31次方就是-2147483648
System.out.println(“正数左移溢出:”+(a<<28)); //-1073741824
System.out.println(“正数左移溢出:”+(a<<29)); //-2147483648
//-12
//before: 1111 1111 1111 1111 1111 1111 1111 0100
//<<28after : 0100 0000 0000 0000 0000 0000 0000 0000
//<<28after : 1000 0000 0000 0000 0000 0000 0000 0000
System.out.println(“负数左移溢出:”+(c<<28)); //1073741824
System.out.println(“负数左移溢出:”+(c<<29)); //-2147483648
System.out.println();

/**
* 5、java有符号右移 >>
*
* 运算方法:
* 按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。
*
* 数学意义:
* 在数字没有溢出的前提下,右移一位相当于除2,右移n位相当于除以2的n次方。
*
*/
//10 : 0000 0000 0000 0000 0000 0000 0000 1010
//>>2after: 0000 0000 0000 0000 0000 0000 0000 0010
System.out.println(“正数有符号右移:”+(b>>2)); //a/2*2 = 2
//-10:1111 1111 1111 1111 1111 1111 1111 0110
//>>2after: 111111 1111 1111 1111 1111 1111 1111 1101
System.out.println(“负数有符号右移:”+(d>>2)); //-3
System.out.println();

/**
* 5、无符号右移 >>>
*
* 运算方法:
* 按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。
* 对于正数来说和带符号右移相同,对于负数来说不同。
*
* 其他结构和>>相似。
*
*/
//10 : 0000 0000 0000 0000 0000 0000 0000 1010
//>>>2after: 0000 0000 0000 0000 0000 0000 0000 0010
System.out.println(“正数无符号右移:”+(b>>>2)); // 正数的情况与>>相同
//-10:1111 1111 1111 1111 1111 1111 1111 0110
//>>>2after: 001111 1111 1111 1111 1111 1111 1111 1101
System.out.println(“负数无符号右移:”+(d>>>2)); //负数高位补0:1073741821
}

public static void main(String[] args) {
BitOperate.bitCalc();
}
}


运算结果:

  1. 正数与运算:8
  2. 负数与运算:-12
  3. 正负数与运算:4
  4. 正数或运算:14
  5. 负数或运算:-10
  6. 正负数或运算:-2
  7. 正数非运算:-13
  8. 负数非运算:11
  9. 正数异或运算:6
  10. 负数异或运算:2
  11. 正负数异或运算:-6
  12. ——————————————–
  13. 正数左移:48
  14. 负数左移:-48
  15. 正数左移溢出:-1073741824
  16. 正数左移溢出:-2147483648
  17. 负数左移溢出:1073741824
  18. 负数左移溢出:-2147483648
  19. 正数有符号右移:2
  20. 负数有符号右移:-3
  21. 正数无符号右移:2
  22. 负数无符号右移:1073741821

/**
* byte、short类型左移
*
* 会自动转换为int类型进行右移
*/
public static void bitShift() {
byte a = 64, b;
int i;
i = a << 2;
b = (byte) (a << 2);
System.out.println(“Original value of a: ” + a);
System.out.println(“i (int): ” + i + “—– b(byte): ” + b);
}

结果:
riginal value of a: 64
i (int): 256—– b(byte): 0

java移位运算的总结:

1.对于左移运算:

1>每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。这意味着当左移的运算数是int 类型时,每移动1位,它的第31位就要被移出并且丢弃;当左移的运算数是long 类型时,每移动1位它的第63位就要被移出并且丢弃。

2>左移都可以使原来的操作数翻倍,程序员们经常使用这个办法来进行快速的2 的乘法。但是你要小心,如果你将1移进高阶位(31或63位),那么该值将变为负值。

3>在对byte 和short类型的值进行移位运算时 , Java将自动把这些类型扩大为 int 型,而且,移位后的值也是int 型;如果左移不超过31位,原来对应各位的值不会丢弃。但是,如果你对一个负的byte 或者short类型的值进行移位运算,它被扩大为int 型后,它的符号也被扩展,结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单办法是将移位运算的结果再转换成byte 型 。

2.对于右移运算:每右移一次,就相当于将该值除以2并且舍弃了余数。你可以利用这个特点将一个整数进行快速的2的除法。当然,你一定要确保你不会将该数原有的任何一位移出。

3.无符号右移(>>>)与右移的区别:每一次右移,>>运算符总是自动地用它的先前最高位的内容补它的最高位。这样做保留了原值的符号。而无符号移动总是在高位(最左边)补0。

4.与C、C++不同,Java中没有无符号型整数,而且明确规定了整型和浮点型数据所占的内存字节数,这样就保证了安全性、鲁棒性和平台无关性。