二进制与位运算
1)二进制和位的概念
十进制: 103
103 = 10^0 × 3 + 10^1 × 0 + 10^2 × 1
2)负数怎么用二进制表达
3)为什么这么设计负数
(为了加法的逻辑是一套逻辑,没有条件转移),那么为啥加法逻辑如此重要呢?
(未理解)
4)打印二进制;直接定义二进制、十六进制的变量
package demo1;
public class Test {
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
// 下面这句写法,可以改成 :
// System.out.print((a & (1 << i)) != 0 ? "1" : "0");
// 但不可以改成 :
// System.out.print((a & (1 << i)) == 1 ? "1" : "0");
// 因为a如果第i位有1,那么(a & (1 << i))是2的i次方,而不一定是1
// 比如,a = 0010011
// a的第0位是1,第1位是1,第4位是1
// (a & (1<<4)) == 16(不是1),说明a的第4位是1状态
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
public static void main(String[] args) {
// 非负数
int a = 78;
System.out.println(a);
printBinary(a);
System.out.println("===a===");
// 负数
int b = -6;
System.out.println(b);
printBinary(b);
System.out.println("===b===");
// 直接写二进制的形式定义变量
int c = 0b1001110;
System.out.println(c);
printBinary(c);
System.out.println("===c===");
// 直接写十六进制的形式定义变量
// 0100 -> 4
// 1110 -> e
// 0x4e -> 01001110
int d = 0x4e;
System.out.println(d);
printBinary(d);
System.out.println("===d===");
}
}
5) 相反数
一个整数 取反+1 ——》得到这个整数的相反数
int a = 78, int b = (~78) + 1, int c = -78
b = c
public class Test {
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
// 下面这句写法,可以改成 :
// System.out.print((a & (1 << i)) != 0 ? "1" : "0");
// 但不可以改成 :
// System.out.print((a & (1 << i)) == 1 ? "1" : "0");
// 因为a如果第i位有1,那么(a & (1 << i))是2的i次方,而不一定是1
// 比如,a = 0010011
// a的第0位是1,第1位是1,第4位是1
// (a & (1<<4)) == 16(不是1),说明a的第4位是1状态
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
public static void main(String[] args) {
// ~、相反数
int a = 78;
System.out.println(a);
printBinary(a);
printBinary(~a);
int e = ~a + 1;
System.out.println(e);
printBinary(e);
System.out.println("===e===");
}
}
6)有符号整数最小值的特殊性
取相反数还是自己
public class Test {
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
// 下面这句写法,可以改成 :
// System.out.print((a & (1 << i)) != 0 ? "1" : "0");
// 但不可以改成 :
// System.out.print((a & (1 << i)) == 1 ? "1" : "0");
// 因为a如果第i位有1,那么(a & (1 << i))是2的i次方,而不一定是1
// 比如,a = 0010011
// a的第0位是1,第1位是1,第4位是1
// (a & (1<<4)) == 16(不是1),说明a的第4位是1状态
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
public static void main(String[] args) {
// int、long的最小值,取相反数、绝对值,都是自己
int f = Integer.MIN_VALUE;
System.out.println(f);
printBinary(f);
System.out.println(-f);
printBinary(-f);
System.out.println(~f + 1);
printBinary(~f + 1);
System.out.println("===f===");
}
}
原因 :
正常情况:
7)常见的位运算(|、&、^、~、<<、>>、>>>)
注意|、&是位运算或、位运算与;||、&&是逻辑或、逻辑与,两者是有区别的
|, &, ^ 与 || &&:
public class Test {
public static void main(String[] args) {
// | & ^
int g = 0b0001010;
int h = 0b0001100;
printBinary(g | h);
printBinary(g & h);
printBinary(g ^ h);
System.out.println("===g、h===");
// 可以这么写 : int num = 3231 | 6434;
// 可以这么写 : int num = 3231 & 6434;
// 不能这么写 : int num = 3231 || 6434;
// 不能这么写 : int num = 3231 && 6434;
// 因为 ||、&& 是 逻辑或、逻辑与,只能连接boolean类型
// 不仅如此,|、& 连接的两侧一定都会计算
// 而 ||、&& 有穿透性的特点
System.out.println("test1测试开始");
boolean test1 = returnTrue() | returnFalse();
System.out.println("test1结果," + test1);
System.out.println("test2测试开始");
boolean test2 = returnTrue() || returnFalse();
System.out.println("test2结果," + test2);
System.out.println("test3测试开始");
boolean test3 = returnFalse() & returnTrue();
System.out.println("test3结果," + test3);
System.out.println("test4测试开始");
boolean test4 = returnFalse() && returnTrue();
System.out.println("test4结果," + test4);
System.out.println("===|、&、||、&&===");
}
public static boolean returnTrue() {
System.out.println("进入了returnTrue函数");
return true;
}
public static boolean returnFalse() {
System.out.println("进入了returnFalse函数");
return false;
}
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
// 下面这句写法,可以改成 :
// System.out.print((a & (1 << i)) != 0 ? "1" : "0");
// 但不可以改成 :
// System.out.print((a & (1 << i)) == 1 ? "1" : "0");
// 因为a如果第i位有1,那么(a & (1 << i))是2的i次方,而不一定是1
// 比如,a = 0010011
// a的第0位是1,第1位是1,第4位是1
// (a & (1<<4)) == 16(不是1),说明a的第4位是1状态
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
}
<<、>>、>>>:
public class Test {
public static void main(String[] args) {
// <<
int i = 0b0011010;
printBinary(i);
printBinary(i << 1);
printBinary(i << 2);
printBinary(i << 3);
System.out.println("===i << ===");
// 非负数 >> >>>,效果一样
printBinary(i);
printBinary(i >> 1);
printBinary(i >> 2);
printBinary(i >>> 2);
System.out.println("===i >> >>>===");
// 负数 >> >>>,效果不一样
int j = 0b11110000000000000000000000000000;
printBinary(j);
printBinary(j >> 2); // 用符号位补
printBinary(j >>> 2); // 都拿0补
System.out.println("===j >> >>>===");
// 非负数 << 1,等同于乘以2
// 非负数 << 2,等同于乘以4
// 非负数 << 3,等同于乘以8
// 非负数 << i,等同于乘以2的i次方
// ...
// 非负数 >> 1,等同于除以2
// 非负数 >> 2,等同于除以4
// 非负数 >> 3,等同于除以8
// 非负数 >> i,等同于除以2的i次方
// 只有非负数符合这个特征,负数不要用
int k = 10;
System.out.println(k);
System.out.println(k << 1);
System.out.println(k << 2);
System.out.println(k << 3);
System.out.println(k >> 1);
System.out.println(k >> 2);
System.out.println(k >> 3);
System.out.println("===k===");
}
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
// 下面这句写法,可以改成 :
// System.out.print((a & (1 << i)) != 0 ? "1" : "0");
// 但不可以改成 :
// System.out.print((a & (1 << i)) == 1 ? "1" : "0");
// 因为a如果第i位有1,那么(a & (1 << i))是2的i次方,而不一定是1
// 比如,a = 0010011
// a的第0位是1,第1位是1,第4位是1
// (a & (1<<4)) == 16(不是1),说明a的第4位是1状态
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
}