位移运算符

package com.lgf.operation;

/**
* 所有的整数类型(除了char 类型之外)都是有符号的整数。
* 这意味着他们既能表示正数,又能表示负数。Java 使用2的补码(two’s complement )
* 这种编码来表示负数,也就是通过将与其对应的正数的二进制代码取反(即将1变成0,将0变成1),然后对其结果加1。
* 例如,-42就是通过将42的二进制代码的各个位取反,即对00101010 取反得到11010101 ,然后再加1,得到11010110 ,即-42 。
* 要对一个负数解码,首先对其所有的位取反,然后加1。
* 例如-42,或11010110 取反后为00101001 ,或41,然后加1,这样就得到了42。
* @author lgf
*
*/
public class BitwiseOperators {
public static void main(String[] args) {
bitwiseNot();
bitwiseAnd();
bitwiseOr();
bitwiseXOR();
leftShiftOperator();
rightShiftOperator();
rightUnsignedShiftOperator();
}

/**
* ~ 按位非(NOT)(一元运算)
* 按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。
*/
public static void bitwiseNot(){
int x = 42; // x = 00000000000000000000000000101010
int y = ~x; // y = 11111111111111111111111111010101 = -43

x = -42; // x = 11111111111111111111111111010110
y = ~x; // y = 00000000000000000000000000101001 = 41
}

/**
* & 按位与(AND) 二元
* 按位与运算符“&”,如果两个运算数都是1,则结果为1。其他情况下,结果均为零。
*/
public static void bitwiseAnd(){
int x = 44; // x = 0101100
int y = 99; // y = 1100011
int z = x & y; // z = 0100000 = 1 * 2^5 = 32

x = - 44; // x = 11111111111111111111111111010100
y = 99; // y = 00000000000000000000000001100011
z = x & y; // z = 00000000000000000000000001000000 = 1 * 2^6 = 64
}

/**
* | 按或(OR) 二元
* 按位或运算符“|”,任何一个运算数为1,则结果为1
*/
public static void bitwiseOr(){
int x = 44; // x = 0101100
int y = 99; // y = 1100011
int z = x | y; // z = 1101111 = 111

x = - 44; // x = 11111111111111111111111111010100
y = 99; // y = 00000000000000000000000001100011
z = x | y; // z = 11111111111111111111111111110111 = -9
}


/**
* ^ 按位异或(XOR) 二元
* 按位或运算符 " ^ ",
* 如果两个运算数都是1,则结果为1。
* 其他情况下,结果均为零。
*/
public static void bitwiseXOR(){
int x = 44; // x = 0101100
int y = 99; // y = 1100011
int z = x ^ y; // z = 1001111 = 79

x = - 44; // x = 11111111111111111111111111010100
y = 99; // y = 00000000000000000000000001100011
z = x ^ y; // z = 11111111111111111111111110110111 = -73
}

/**
* 左移运算符<<使指定值的所有位都左移规定的次数。
* 它的通用格式如下所示: value << num 这里
* num 指定要移位值value 移动的位数。也就是,左移运算符<<使指定值的所有位都左移num位。
* 每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。
* 这意味着当左移的运算数是int 类型时,每移动1位它的第31位就要被移出并且丢弃;
* 当左移的运算数是long 类型时,每移动1位它的第63位就要被移出并且丢弃。
*
* 在对byte 和short类型的值进行移位运算时,你必须小心。
* 因为你知道Java 在对表达式求值时,将自动把这些类型扩大为 int 型,
* 而且,表达式的值也是int 型。对byte 和short类型的值进行移位运算的结果是int 型,
* 而且如果左移不超过31位,原来对应各位的值也不会丢弃。
* 但是,如果你对一个负的byte 或者short类型的值进行移位运算,它被扩大为int 型后,它的符号也被扩展。
* 这样,整数值结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。
* 这样做的最简单办法是将结果转换为byte 型。下面的程序说明了这一点:
*/
public static void leftShiftOperator(){
int x = 11; // x = 1011
int y = x << 3; // y = 1011000

x = -11; //x = 11111111111111111111111111110101
y = x << 3; //y = 11111111111111111111111110101000
byte i = 64; // i = 001000000 64
int j = i << 2; // j = 100000000 256
byte z = (byte)(i << 2); // z = 00000000 0

int num = 0xFFFFFFE; // num = 00001111111111111111111111111110
//i = 0 num=00011111111111111111111111111100 536870908
for(i=0; i<5; i++) { //i = 1 num = 00111111111111111111111111111000 1073741816
num = num << 1; //i = 2 num = 01111111111111111111111111110000 2147483632
//printBinary(num); //i = 3 num = 11111111111111111111111111100000 -32
} // i = 4 num = 11111111111111111111111111000000 -64


num = -0xFFFFFFE; // num = 11110000000000000000000000000010 -268435454
// i = 0 num = 11100000000000000000000000000100 -536870908
for(i=0; i<5; i++) { // i = 1 num = 11000000000000000000000000001000 -1073741816
num = num << 1; // i = 2 num = 10000000000000000000000000010000 -2147483632
//printBinary(num); // i = 3 num = 00000000000000000000000000100000 32
} // i = 4 num = 00000000000000000000000001000000 64
}

/**
* 右移运算符>>使指定值的所有位都右移规定的次数。
* 它的通用格式如下所示: value >> num 这里,
* num 指定要移位值value 移动的位数。
* 也就是,右移运算符>>使指定值的所有位都右移num位
*
* 右移时,被移走的最高位(最左边的位)由原来最高位的数字补充。
* 例如,如果要移走的值为负数,每一次右移都在左边补1,
* 如果要移走的值为正数,每一次右移都在左边补0,
* 这叫做符号位扩展(保留符号位)(sign extension ),在进行右移操作时用来保持负数的符号
*/
public static void rightShiftOperator(){
int x = 35; // x = 100011 35
int y = x >> 2; // y = 1000 8

x = 32; // x = 100000
y = x >> 2; // y = 1000 8

x = -32; // x = 11111111111111111111111111100000 -32
y = x >> 2; // y = 11111111111111111111111111111000 -8

x = -1; // x = 11111111111111111111111111111111
y = x >> 2; // y = 11111111111111111111111111111111
}

/**
* 无符号右移运算符>>>
* 不管运算数的初值是什么,你希望移位后总是在高位(最左边)补0。
* 这就是人们所说的无符号移动(unsigned shift )。
* 这时你可以使用Java 的无符号右移运算符>>> ,它总是在左边补0。
*/
public static void rightUnsignedShiftOperator(){
int x = 35; // x = 100011 35
int y = x >>> 2; // y = 1000 8

x = 32; // x = 100000
y = x >>> 2; // y = 1000 8

x = -32; // x = 11111111111111111111111111100000 -32
y = x >>> 2; // y = 00111111111111111111111111111000 1073741816

x = -1; // x = 11111111111111111111111111111111
y = x >>> 2; // y = 00111111111111111111111111111111 1073741823
printBinary(y);
}

public static void printBinary(int i){
System.out.println("数值 " + i + " 对应的二进制为: " + Integer.toBinaryString(i) + " 一共:" + Integer.toBinaryString(i).length() + " 位");
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值