/*
运算符五 位运算符
左移 << 3<<2 结果 12
右移 >> 3>>2 结果 1
无符号右移 >>> 3>>2 结果 1
与运算 & 6&3 结果 2
或运算 | 6|3 结果 7
异或运算 ^ 6^3 结果 5
取反运算 ~ ~6 结果 -7
位移运算符操作的都是整数数据
& | ^ 是逻辑运算符还是位运算符根据前后变量类型判断
布尔型是逻辑运算,数值型是位运算
位运算针对底层二进制码做操作
左移两位相当于把二进制码后加两个0(不分正负),前面去掉两位
根据二进制转十进制的规律相当于对十进制数乘2的2次幂
在一定范围内(避免将1移动到最高位),每向左移移位相当于乘2(负数也是这个规律)
面试题;以最高效的方式计算 28
使用位移 2<<3 (22^3) 或者 8<<1 (8*2^1)
右移两位相当于把二进制码后面去掉两位,前面增加两位,补1还是补0取决原来的正负,正数用00补,负数用11补
无符号右移前面都用0来补位置
*/
import java.util.Scanner;
class BitMoveTest {
public static void main(String[] args) {
int i1 = 21;//21 二进制码为 0000 0000 0000 0000 0000 0000 0001 0101 (int为2个字Word4个字节byte32个bit)
int i2 = 21 << 2;// 左移两位后二进制码为 0000 0000 0000 0000 0000 0000 0101 0100
System.out.println("i1<<2=" + (21 << 2));//输出21*2^2=21*4=84
System.out.println("i1<<3=" + (21 << 3));//输出21*2^3=21*8=168
System.out.println("i1<<27=" + (21 << 27));//输出-1476395008, 因为1被最高位(第32位),变为负数
System.out.println("-i1<<2=" + (-21 << 2));//输出-21*2^2=21*4=-84
System.out.println("-i1<<3=" + (-21 << 3));//输出-21*2^3=21*8=-168
System.out.println("-i1<<27=" + (-21 << 27));//输出1476395008, 因为1被最高位(第32位),变为负数
int m = 12;
int n = 5;
System.out.println("m & n =" + (m & n));//输出4
System.out.println("m | n =" + (m | n));//输出13
System.out.println("m ^ n =" + (m ^ n));//输出9
System.out.println("m =" + (m ^ n ^ n));//输出12,m逻辑异或运算两次得到原数值
System.out.println("~ m =" + (~ m));//输出-13
System.out.println("m =" + (~ ~ m));//输出12
/*
0 0 0 0 1 1 0 0 12
& 0 0 0 0 0 1 0 1 5 二进制各位做逻辑与运算,1为true 0为false
0 0 0 0 0 1 0 0 4
0 0 0 0 1 1 0 0 12
| 0 0 0 0 0 1 0 1 5 二进制各位做逻辑或运算,1为true 0为false
0 0 0 0 1 1 0 1 13
0 0 0 0 1 1 0 0 12
^ 0 0 0 0 0 1 0 1 5 二进制各位做逻辑异或运算,1为true 0为false
0 0 0 0 1 0 0 1 9
~ 0 0 0 0 1 1 0 0 12 二进制包括符号位各位做取反运算,1变为0 ,0变为1
1 1 1 1 0 0 1 1 -13 -13的取反运算得到12
*/
//练习:交换两个变量的值
int num1 = 10;
int num2 = 20;
System.out.println("num1 =" + num1 + ",num2 = " + num2);
//方式1,使用临时变量,常用
int temp = num1;
num1 = num2;
num2 = temp;
System.out.println("num1 =" + num1 + ",num2 = " + num2);
//方式二,使用加法,不用定义临时变量,节省资源
//缺点:1,使用相加可能超出变量范围
// 2,只对数值型变量有用,其它类型不行
num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2;
System.out.println("num1 =" + num1 + ",num2 = " + num2);
//方式三,使用位运算符,利用逻辑异或的性质 m = m ^ n ^ n n = m ^ n ^ m。使用m^n作为临时变量
//优点同方式二,且不会超出范围,缺点,只对数值变量适用。
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;
System.out.println("num1 =" + num1 + ",num2 = " + num2);
//如何求一个0-255范围内的整数的十六进制,例如60的16进制表示形式为3c
//方法一,调用类直接求
String str1 = Integer.toBinaryString(60);
String str2 = Integer.toHexString(60);
System.out.println(str1);
System.out.println(str2);
//方法二,手写计算,综合利用位移运算,与二进制16进制的换算(二进制数每四位计算一个值为16进制的1位,从右到左)
Scanner scan = new Scanner(System.in);//创建Scanner实例
System.out.println("请输入0-255内的整数");
int i3 = scan.nextInt();//从键盘输入需要转换的整数
int i4 = i3 & 15;//15的二进制是00001111,参与&运算得出的结果就是i3的二进制的后四位
String a = (i4 > 9)?(char)(i4 -10 + 'A') +"" : i4 + "";//使用三元运算符判断16进制最后那位输出的是数字还是字符
//因为十六进制中没有10,第10为A, i4-10+'A'就可以输出C,前面也需要强转成char类型才能这样算。后面 + ""是为了转为String型
int temp1 = i3 >>> 4;// 无符号右移四位后就得到了i3的另外四位
int i5 = temp1 & 15;//原理同上
String b = (i5 > 9)?(char)(i5 -10 + 'A') +"" : i5 + "";//原理同上
if(i3 >= 0 && i3 <=255){
System.out.println("输入数字的16进制为" + b + "" + a);
}else{
System.out.println("输入的数字不在范围内");
}
}
}