二进制

逢二进一的计数规则,是计算机底层采用的计数规则.

原理:

案例:

public static void main(String[] args) {
    /**
     * 展示一个整数的本质-- 2进制
     **/
    int n = 50;
    System.out.println(n);//110010 -> "50"  
    //toBinaryString方法本质是展示n在内存中的
    //2进制存储情况
    System.out.println(Integer.toBinaryString(n));  

    for(int i=0;i<50; i++) {
        System.out.println(Integer.toBinaryString(i));
    }
}

关于容量大小

  1. 位bit,2进制数的一个数字称为一个位,如:整数是32位数
  2. 字节Byte, 8位,最初用于表示计算机处理的一个"字符", 称为字节. 泛指8位2进制,称为一个字节. 如: 整数4字节. 字节是计算机中衡量数量的最常用单位.
  3. 字节数量表示方式, 经常用于表示计算机中零件的容量:

    数量: 1024Byte = 1KByte = 1K 
          1024KByte = 1MByte = 1M(兆)
          1024MByte = 1GByte = 1G
          1024GByte = 1TByte = 1T
          1024TByte = 1PByte = 1P 
    
    硬盘和U盘的容量: 1000K = 1M    
    
  4. 字符: Java字符类型16位,支持常用字符范围(基本编码平面)0~65535, 两个字节.

  5. 网络速率以 bit/s为单位! 如: 100M网络是指每秒传送100Mbit数据.核算为字节需要除以8, 相当于 11M Byte/S 左右

16进制

16进制:是2进制的缩写形式,编程时候用于简化书写2进制. 2进制从最低位到高位每4位2进制可以缩写为一位16进制数.

原理:

案例:

public static void main(String[] args) {
    /**
     * Java 7 提供2进制直接量
     * 0b 开头
     * 后面接2进制直接量,只能包含01数字
     * 
     * 16进制用于缩写2进制, 从低位开始,每4位2进制数
     * 缩写为一位16进制数
     */
    //        高位                                                低位
    int n = 0b01101101110111101110001110111010;
    System.out.println(Integer.toBinaryString(n)); 
    n = 0x6ddee3ba;
    System.out.println(Integer.toBinaryString(n)); 

    //利用16进制输出特殊字符
    char c = 0x5abd;
    System.out.println(c); 
    c = 0x2552;
    System.out.println(c); 
}

补码

补码: 将一个固定位数的2进制数,分一半作为负数,而设计的一套编码规则. 其目的是为了解决 "负数编码" 和计算问题.

以4位数为例子研究补码, 方便研究, 只要推广一下就可以得到32位甚至更高位数补码

计算机底层采用2进制补码:

案例1

public static void main(String[] args) {
    /**
     * 负数的编码: 补码
     */
    int n = -3;
    System.out.println(Integer.toBinaryString(n));

    int max = 0b01111111111111111111111111111111;
    System.out.println(max);
    System.out.println(Integer.toBinaryString(max));
    max = Integer.MAX_VALUE;
    System.out.println(Integer.toBinaryString(max));

    int min = 0x80000000;
    System.out.println(Integer.toBinaryString(min));
    min = Integer.MIN_VALUE;
    System.out.println(Integer.toBinaryString(min));

    System.out.println(min-max);


    n = -1;
    System.out.println(Integer.toBinaryString(n));  

    n = -11;
    System.out.println(Integer.toBinaryString(n));  
    n = -43;
    System.out.println(Integer.toBinaryString(n));
}

案例2:

public static void main(String[] args) {
    /**
     * 负数的补码
     */
    for(int i=-50; i<=0; i++) {
        System.out.println(Integer.toBinaryString(i));  
    }
}

案例3:

public static void main(String[] args) {
    /**
     * long 类型 64位补码
     */
    long max = Long.MAX_VALUE;
    long min = Long.MIN_VALUE;
    long n = -1L;
    long m = -3L;
    System.out.println(Long.toBinaryString(max));
    System.out.println(Long.toBinaryString(min));
    System.out.println(Long.toBinaryString(n));
    System.out.println(Long.toBinaryString(m));

}

案例4: 互补对称现象

public static void main(String[] args) {
    /**
     * 补码的互补对称现象
     * ~ 取反计算, 将一个数2进制中0变1, 1变0 
     */
    int n = -1;
    int m = ~n;
    System.out.println(m); //0

    //验证互补对称 : -n = ~n + 1, 最小值除外
    n = 1;
    m = ~n + 1;
    System.out.println(m); //-1

    n = 2;
    m = ~n + 1;
    System.out.println(m); //-2

    n = -1;
    m = ~n + 1;
    System.out.println(m); //1

    n = -2;
    m = ~n + 1;
    System.out.println(m); //2

    n = -10000;
    m = ~n + 1;
    System.out.println(m); //10000

    n = 20000;
    m = ~n + 1;
    System.out.println(m); //-20000

    int max = Integer.MAX_VALUE;
    m = ~max+1;
    System.out.println(m); //

    //最小值不成立
    int min = Integer.MIN_VALUE;
    m = ~min+1;
    System.out.println(m); //

}

2进制计算

2进制运算符

~ 取反运算
& 与
| 或
>>> 右移位计算
>>  数学右移位
<<  左移位计算

与计算 &

基本规则 逻辑乘法(有0则0):

0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1

计算时候需要将两个数, 对齐位置, 对应的位置数字进行与计算

举个栗子:

n  =   01111101 10111010 00101011 11100101
m  =   00000000 00000000 00000000 11111111  Mask/面具/掩码 8位掩码
k=n&m  00000000 00000000 00000000 11100101

如上计算称为掩码计算, 其作用是将n的最后8位数截取下来, 存储到k中.

代码:

int n = 0x7cba2be5;
int m = 0xff;
int k = n&m;
System.out.println(Integer.toBinaryString(n));
System.out.println(Integer.toBinaryString(m));
System.out.println(Integer.toBinaryString(k));

>>> 右移位计算

将一个数的2进制整体位数向右移动, 低位溢出舍弃, 高位补0

举个栗子

n  =    01111101 10111010 00101011 11100101
m=n>>>1 001111101 10111010 00101011 1110010
k=n>>>8 00000000 01111101 10111010 00101011 

代码:

int n = 0x7cba2be5;
int m = n>>>1;
int k = n>>>8;
//拆分int为4个Byte
int b1 = (n>>>24) & 0xff;
int b2 = (n>>>16) & 0xff;
int b3 = (n>>>8) & 0xff;
int b4 = (n>>>0) & 0xff;

拆分int为4个Byte

n  =   01111101 10111010 00101011 11100101

b1 =   00000000 00000000 00000000 01111101
b2 =   00000000 00000000 00000000 10111010
b3 =   00000000 00000000 00000000 00101011 
B4 =   00000000 00000000 00000000 11100101 

b1 = (n>>>24)&0xff;
b2 = (n>>>16)&0xff;
b3 = (n>>>8)&0xff;
b4 = (n>>>0)&0xff;

| 或

规则: 逻辑加法(有1则1)

0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1

对齐位置, 对应的数位进行或计算

举个栗子:

n =    00000000 00000000 11011011 00000000
m =    00000000 00000000 00000000 11011110  
k=n|m  00000000 00000000 11011011 11011110 

自行编写案例测试!

合并4个Byte为int

原理:

案例:

/**
 * 将4个Byte b1 b2 b3 b4 拼接为一个int
 */
k = (b1<<24)|(b2<<16)|(b3<<8)|(b4<<0);

System.out.println(Integer.toBinaryString((b1<<24)));  
System.out.println(Integer.toBinaryString((b2<<16)));  
System.out.println(Integer.toBinaryString((b3<<8)));  
System.out.println(Integer.toBinaryString((b4<<0)));  
System.out.println(Integer.toBinaryString(k));