什么是2进制
逢2进1的计数规则.

案例:
1 public class Demo01 {
2
3 public static void main(String[] args) {
4 /**
5 * 第一次 看见2进制
6 */
7 int i = 50; //110010
8 //在println(i)输出时候,Java会使用
9 //API(方法)将2进制转换为10进制字符串
10 System.out.println(i); //"50"
11 //Java提供了方法toBinaryString可以
12 //看到内存中存储的2进制数据
13 System.out.println(
14 Integer.toBinaryString(i));
15 for(i=0; i<=50; i++) {
16 System.out.println(
17 Integer.toBinaryString(i));
18 }
19
20 }
21 }
计算机和2进制的关系

16进制
16进制用于简写(缩写)2进制. 因为2进制书写冗长\麻烦\易错, 因为16进制基数是2的整次幂, 所以4位2进制可以缩写为一个16进制数字.
缩写规则: 将2进制从后向前,每4位2进制数缩写为一个16进制.

案例:
1 public static void main(String[] args) {
2 /**
3 * 直接书写2进制, Java 7 以后支持的
4 * 特性, 可以以0b开头书写2进制数据
5 */
6 int n = 0b110010;
7 System.out.println(n);
8
9 //2进制书写麻烦
10 n = 0b11010011111101010010111101;
11 //16进制简写2进制, 使用起来方便
12
13 int i = 0x77a65fa8;
14 System.out.println(
15 Integer.toBinaryString(i));
16 }
补码
计算机中的一种解决负数(有符号数)问题的编码, 其核心目的是将固定位数的2进制数,分一半作为负数.
补码是如何将固定位数的2进制分一半作为负数的?
以4位2进制为例讲解补码编码规则:
- 计算时候, 超过4位时候自动溢出舍弃, 保持数字始终是4位2进制数.
- 高位为1的作为负数, 高位为0的作为整数
- 负数编码由正数反向推算出来.
- 负数与正数正好互补对称: 顾称为补码.
案例1
1 public static void main(String[] args) {
2 /**
3 * 补码
4 */
5 int n = -13;
6 System.out.println(Integer.toBinaryString(n));
7 for(int i=-50; i<0; i++) {
8 System.out.println(
9 Integer.toBinaryString(i));
10 }
11 }
案例2: 特殊值
1 public static void main(String[] args) {
2 int max = Integer.MAX_VALUE;
3 int min = Integer.MIN_VALUE;
4 System.out.println(max);
5 System.out.println(min);
6 System.out.println(Integer.toBinaryString(max));
7 System.out.println(Integer.toBinaryString(min));
8 //int n = -1;
9 //int n = 0b11111111111111111111111111111111;
10 int n = 0xffffffff;
11 System.out.println(Integer.toBinaryString(n));
12 System.out.println(n); //按照10进制输出:-1
13 //溢出结果: 可能是正数也可能是负数!
14 int k = 100;
15 System.out.println(k+max);
16 System.out.println(k+max+max);
17 //如上运算结果说明 补码是一个环形编码!
18 }
补码的互补对称性:
计算原理:
n 00000000 00000000 00000000 00110010 50 ~n 11111111 11111111 11111111 11001101 -51 ~n+1 11111111 11111111 11111111 11001110 -50
互补对称实验案例:
1 int n = 50; 2 int m = ~n + 1; 3 System.out.println(m);//-50 4 System.out.println(Integer.toBinaryString(n)); 5 System.out.println(Integer.toBinaryString(~n)); 6 System.out.println(Integer.toBinaryString(~n+1));
经典面试题目:
System.out.println(~5); 如上代码的输出结果:( D ) A.5 B.6 C.-5 D.-6 System.out.println(~-5); 如上代码的输出结果:( A ) A.4 B.5 C.6 D.7
2进制运算
运算符号:
~ 取反 & 与 | 或 >> 右移位 >>> 逻辑右移位 << 左移位
&与计算(逻辑乘法)
基本规则: 有0则为0
0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 = 1
计算时候,需要将两个数字对其位数, 对应位置数字计算与运算:
举个栗子:
n = 01110111 01010100 10111111 11110111 m = 00000000 00000000 00000000 11111111 mask k=n&m 00000000 00000000 00000000 11110111
如上计算的意义: 如上是掩码(Mask)计算(拆分计算), 其拆分结果 k 是 n 的最后8位(1字节)
实验
int n = 0x7754bff7; int m = 0xff; //8位掩码(Mask): 1的个数有8个 int k = n&m; //按照2进制验证结果 System.out.println(Integer.toBinaryString(n)); System.out.println(Integer.toBinaryString(m)); System.out.println(Integer.toBinaryString(k));
>>> 逻辑右移位计算
将2进制数位整体向右移位, 低位自动溢出, 高位补0:
案例:
1 public static void main(String[] args) {
2 /**
3 * 移位计算案例
4 */
5 int n = 0x7754bff7;
6 int m = n>>>1;
7 int k = n>>>2;
8 int g = n>>>8;
9 int b3 = (n>>>8) & 0xff;
10 System.out.println(Integer.toBinaryString(n));
11 System.out.println(Integer.toBinaryString(m));
12 System.out.println(Integer.toBinaryString(k));
13 System.out.println(Integer.toBinaryString(g));
14 System.out.println(Integer.toBinaryString(b3));
15 }
拆分整数为byte
案例:
1 public static void main(String[] args) {
2 /**
3 * 将一个整数int拆分为4个byte
4 * 案例: 将一个整数long拆分为8个byte
5 */
6 int n = 0x7745abd7;
7 int b1 = (n>>>24) & 0xff;
8 int b2 = (n>>>16) & 0xff;
9 int b3 = (n>>>8) & 0xff;
10 int b4 = n & 0xff;
11 System.out.println(Integer.toBinaryString(n));
12 System.out.println(Integer.toBinaryString(b1));
13 System.out.println(Integer.toBinaryString(b2));
14 System.out.println(Integer.toBinaryString(b3));
15 System.out.println(Integer.toBinaryString(b4));
16 /**
17 * 将一个整数long拆分为8个byte
18 */
19 long l = 0x76ab3fed723e7828L;
20 b1 = (int)((l>>>56)& 0xff);
21 b2 = (int)((l>>>48)& 0xff);
22 b3 = (int)((l>>>40)& 0xff);
23 b4 = (int)((l>>>32)& 0xff);
24 int b5 = (int)((l>>>24)& 0xff);
25 int b6 = (int)((l>>>16)& 0xff);
26 int b7 = (int)((l>>>8)& 0xff);
27 int b8 = (int)((l>>>0)& 0xff);
28 //验证...
29 System.out.println(Long.toBinaryString(l));
30 }
| 或运算(逻辑加法)
基本规则: 有1则1
0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1
计算时候, 将两个数的数位对齐对应位进行或计算.
举个栗子:
n= 00000000 00000000 00000000 10011101 m= 00000000 00000000 11011111 00000000 k=n|m 00000000 00000000 11011111 10011101
如上计算意义: 将n和m两个数字进行拼接计算.
验证:
int n = 0x9d; int m = 0xdf00; int k = n|m; //按照2进制输出
<< 左移位
将2进制数字每个位向左移动, 高位溢出, 低位补0
移位计算的数学意义
回顾10进制小数点移动计算:
// 89191. // 891910. // 8919100. // 10进制时候, 数字向左移动一次, 数值扩展10倍 // 110010. 50 // 1100100. 100 = 50<<1 // 11001000. 200 = 50<<2 // 2进制时候, 数字向左移动一次, 数值扩大2倍 // 110010. 50 // 11001. 25 = 50>>1 // 1100. 12 = 50>>2 向小方向取整数
案例:
/** * 移动计算的数学意义 */ int n = 50; System.out.println(n); System.out.println(n<<1); System.out.println(n<<2); System.out.println(n<<3); System.out.println(n>>1); System.out.println(n>>2);
>> >>> 的区别
>> 称为数学右移位计算, 当正数时候(高位为0), 高位补0, 当负数时候(高位为1) 高位补1, 其运算结果是数学除法, 向小方向取整.
>>> 称为逻辑右移位计算, 无论正负高位都补0, 负数时候不符合数学运算结果
举个栗子:
n = 11111111 11111111 11111111 11001110 -50 m=n>>1 111111111 11111111 11111111 1100111 -25 g=n>>2 1111111111 11111111 11111111 110011 -13 k=n>>>1 011111111 11111111 11111111 1100111 比最大值小24
>>运算是接近数学结果: 除以2向小方向取整数.
>>>单纯将数位向右移动, 其结果不考虑数学意义, 进行数字拆分合并时候采用纯正的右移动.
面试案例: 替代2的整数倍乘法, 使用采用数学移位!
n * 32 可以替换为 ( n<<5 ) n / 2 (n>=0) 可以替换为 ( n>>1 )








来源:https://www.cnblogs.com/hello4world/p/12094379.html