二进制
程序员文章站
2022-04-04 20:05:07
...
计算机内部一切都是2进制!
变量, 数据都是2进制:
数据类型: byte short int long float double boolean char
案例:
什么是二进制?
逢二进一的计数规律
2进制原理
案例:
for(int i=0; i<20; i++){
System.out.println(
Integer.toBinaryString(i));
}
Java 利用算法支持10进制
- 底层采用2进制
- 人可以使用10进制操作计算机
-
利用算法(方法)
-
将"10进制字符串"转换为2进制
int Integer.parseInt(String)
-
将2进制(int)转换为"10进制字符串"
String Integer.toString(int)
-
16进制
逢16进1 的计数规律, 在计算机编程中用于简写2进制!
每个16进制的数字可以缩写4位2进制数.
案例:
补码
为了将2进制数据分出一半来表示负数, 设计了补码:
案例:
/** * 补码 */ public class Demo03 { public static void main(String[] args) { for(int i=-10; i<=10; i++){ System.out.println( Integer.toBinaryString(i)); } for(long i=-10; i<=10; i++){ System.out.println( Long.toBinaryString(i)); } } }
补码的最大值和最小值:
因为补码正负数互补对称, 故称为补码:
面试题 1:
int n = 0xffffffff;
System.out.println(n);
如上代码输入结果:
A.2147483647 B.-2147483647 C.2147483648 D.-2147483648 E.-1
>答案:E
面试题 2:
int max = Integer.MAX_VALUE;
System.out.println(Integer.toBinaryString(max));
如上代码输入结果:
A.11111111111111111111111111111111
B.1111111111111111111111111111111
C.10000000000000000000000000000000
D.1000000000000000000000000000000
>答案:B
面试题 3:
System.out.println(~800+1);
代码输出结果: -800
System.out.println(~800);
代码输出结果: -801
System.out.println(~-800);
代码输出结果: 799
2进制运算符
~ 取反 & 与运算 | 或运算
右移位运算 数学右移位运算 << 左移位运算
& 与运算
按位与运算 (逻辑乘法)
规则:
1 & 1 = 1
0 & 1 = 0
1 & 0 = 0
0 & 0 = 0
案例:
n = 01001000 00100101 11010101 01111010
m = 00000000 00000000 00000000 11111111 : mask
n&m-----------------------------------------
k 00000000 00000000 00000000 01111010
用途: 掩码(Mask:面具)运算, 可以将一个数拆分
int n = 0x4825d57a;
int m = 0xff;
int k = n&m;
//输出n m k 2进制
掩码运算的数学意义
32 16 8 4 2 1
1 0 0 1 1 1 n
0 0 0 0 1 1 m
n&m = n%4
m = 0x3;
for(int i=0; i<20; i++){
int x = i&m;
int y = i%4;
System.out.println(x+","+y);
}
32 16 8 4 2 1
0 0 1 0 0 1 i = 5 6 7 8 9 10
0 0 0 0 1 1 m
i & m = 1 == i % 4 = 1
案例:
/**
* 掩码运算相当于2整次幂的余数
*
* n&0x1 等于 n%2
* n&0x3 等于 n%4
* n&0x7 等于 n%8
* n&0xf 等于 n%16
*/
public class Demo06 {
public static void main(String[] args) {
int m = 0x3;
for(int i=0; i<20; i++){
int x = i&m;
int y = i%4;
System.out.println(x+","+y);
}
}
}
经典题目:
优化运算 n>0, n%8 为( )
答案: n&0x7
| 或运算
按位或运算 (逻辑加法)
规则:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
案例:
n = 00000000 00000000 00000000 10010110
m = 00000000 00000000 11000110 00000000
n|m ---------------------------------------
00000000 00000000 11000110 10010110
颜色拼接: 将3个颜色分量合并为一个RGB色(int)
int r = 00000000 00000000 00000000 11000101
int g = 00000000 00000000 00000000 10010010
int b = 00000000 00000000 00000000 00100111
int r = 00000000 11000101 00000000 00000000
int g = 00000000 00000000 10010010 00000000
int b = 00000000 00000000 00000000 00100111
rgb = r | g | b;
int rgb = 00000000 11000101 10010010 00100111
Java :
int r = 0xc50000;
int g = 0x9200;
int b = 0x27;
int rgb = r|g|b;
JFrame frame = new JFrame();
frame.setSize(200,300);
frame.setBackground(new Color(rgb));
移位运算
>>> 逻辑右移位
将2进制数字向右移动, 低位移出, 高位补0
规则:
高位 低位
n = 00100101 01111001 10010011 00100011
2 5 7 9 9 3 2 3
m = n>>>1
m = 000100101 01111001 10010011 0010001
案例: 拆分rgb为单独颜色分量
int rgb = 00000000 01111001 10010011 00100011
int r = (rgb >>> 16) & 0xff;
int g = (rgb >>> 8) & 0xff;
int b = rgb & 0xff;
案例:
public class Demo08 {
public static void main(String[] args) {
//逻辑右移位运算
int n = 0x25799323;
int m = n>>>1;
System.out.println(
Integer.toBinaryString(n));
System.out.println(
Integer.toBinaryString(m));
//将RGB色拆分为3个颜色分量 r,g,b
int rgb = 0x799323;
// r g b
int r = (rgb>>>16) & 0xff;
int g = (rgb>>>8) & 0xff;
int b = rgb & 0xff;
System.out.println(
Integer.toBinaryString(rgb));
System.out.println(
Integer.toBinaryString(r));
System.out.println(
Integer.toBinaryString(g));
System.out.println(
Integer.toBinaryString(b));
//将颜色分量r,g,b合并为一个RGB颜色
int color = (r<<16)|(g<<8)|b;
System.out.println(
Integer.toBinaryString(color));
}
}
移位运算的数学意义
引子: 10进制移动小数点运算
如: 437812. 小数点向右移动
结果 4378120. 差10倍
如果看作小数点不动, 数字向左移动, 数字向左移动一次差10倍
如: 437812. 小数点向右移动
结果 4378120. 差10倍
2进制有同样规律: 数字向左移动, 数字向左移动一次差2倍
n = 00000000 00000000 00000000 00010010 18
m=n<<1
m = 0000000 00000000 00000000 000100100 36
m=n<<2
m = 000000 00000000 00000000 0001001000 72
案例:
/**
* << 运算案例
*/
public class Demo09 {
public static void main(String[] args) {
int n = -18;
for(int i=0; i<5; i++){
int m = n<<i;
System.out.println(m);
System.out.println(Integer.toBinaryString(m));
}
}
}
>>> 区别 >>
正数(符号位是0) >>> 和 >> 没有区别 负数(符号位是1) >>> 高位补0, >> 高位补 1, 高位补1时候保持是负数, 符合数学/2规律, 溢出时候向小方向取整数
案例:
/**
* >>> 与 >> 的区别
*/
public class Demo10 {
public static void main(String[] args) {
int n = -18;
for(int i=0; i<5; i++){
int m = n>>i;
System.out.println(m);
System.out.println(Integer.toBinaryString(m));
}
}
}
经典面试题
优化 n*8 为 ( ? )
答案: n<<3
2进制运算的用途:
互联网, 文件都是按照Byte为单位传输数据.