Day28API-计算机的二进制工作原理

二进制

1.1 什么是2进制

逢2进1的计数规则

public class Demo02 {
    public static void main(String[] args) {
        /*
         * Java 在编译阶段, 将10进制字面量都
         * 编译为2进制数
         * Integer.toBinaryString(n) 将n按照
         * 内存实际存储的情况,输出,
         * 输出时候高位0省略
         */
        int n = 666; //n = 666
        System.out.println(Integer.toBinaryString(n));
        System.out.println(n); //1010011010->"666"
    }
}

1.2 什么是16进制

逢16进1的计数规则, 在计算机编程中, 采用16进制简写2进制。

由于16进制的基数16是2进制基数2的4次方,所以,可以每4个2进制数缩写为1位16进制。

请添加图片描述

public class Demo03 {
    public static void main(String[] args) {
        /*
         * 2进制书写繁琐
         * Java 7 开始提供了2进制直接量前缀0b
         * 使用下划线分隔,不影响数值
         * 采用16进制缩写
         */
        int n = 0b10_1101_1001; //1+8+16+64+128+512
        System.out.println(n);
        n = 0b1011_1110_1001_1111_1000_1010_1010;
        System.out.println(Integer.toBinaryString(n));
        n = 0xbe9f8aa;
        System.out.println(Integer.toBinaryString(n));
    }
}

1.3 补码

计算机中用于处理负数的编码, 编码思路将固定位数的2进制,分一半作为负数使用。

高位为1 的作为负数, 高位为0的作为正数, 最高位称为符号位, 注意符号位参与运算。

采用4位2进制数,设计为补码, 讨论编码方式, 规定: 计算时候保持4位数,多于的位数自动移除。

请添加图片描述

package binary;

public class Demo04 {
    public static void main(String[] args) {
        /*
         * int 类型的编码
         */
        int max = Integer.MAX_VALUE;
        int min = Integer.MIN_VALUE;
        System.out.println(max);
        System.out.println(Integer.toBinaryString(max));
        System.out.println(min);
        System.out.println(Integer.toBinaryString(min));
        int n = -1;
        System.out.println(Integer.toBinaryString(n));
        n = -3;
        System.out.println(Integer.toBinaryString(n));
        n = -28;
        System.out.println(Integer.toBinaryString(n));
    }
}

正数的规律: 2进制转换为10机制

00000000000000000000000000000000 = 0
00000000000000000000000000011011 = 1+2+8+16 = 27

负数的规律:负数补码转换为10进制。

11111111111111111111111111111111  = -1
11111111111111111111111111111101  = -1-2 = -3
11111111111111111111111111111100  = -1-1-2 = -4
11111111111111111111111111100100  = -1-1-2-8-16 = -28

互补对称性质!这个是巧合, 在进行编码时候,完成的方案存在对称性质: -n = ~n+1

package binary;

public class Demo05 {
    public static void main(String[] args) {
        /*
         * 补码对称
         */
        int n = 56;
        int m = ~n + 1;
        System.out.println(m); //-56
        System.out.println(~56);//-57
        //运算过程分析
        System.out.println(Integer.toBinaryString(n));
        System.out.println(Integer.toBinaryString(~n));
        System.out.println(Integer.toBinaryString(~n+1));
        //注意:最小值,不能取相反数!
        int min = Integer.MIN_VALUE;
        int k = -min;
        System.out.println(k);
    }
}

原理:

00000000000000000000000000111000 = 8+16+32 = 56
11111111111111111111111111000111 = -1-8-16-32 = -57
11111111111111111111111111001000 = -1-1-2-4-16-32 = -56

1.4 二进制运算

运算符号:

&|~<< 左移位
>>> 逻辑右移位
>> 数学右移位

(1) 与 &

逻辑乘法, 有0则0

0 & 0 = 0
1 & 0 = 0
0 & 1 = 0
1 & 1 = 1

运算时候, 将两个2进制数,对其位, 对应的位进行与运算

n =        01011101 01110110 11001110 00101101
m =        00000000 00000000 00000000 11111111
k = n & m  00000000 00000000 00000000 00101101   

经典运算:掩码运算, 将一个2进制数字后n位截取下来的运算

  • 将数据进行拆分
  • 获取除以2的n次方的余数
00000000 00000000 00000000 00101101 = 1+4+8+32 = 45 
45%8=5
00000000 00000000 00000000 00000101 = 1+4= 5 
00000000 00000000 00000000 00101100 = 4+8+32 = 44
44%8=4
00000000 00000000 00000000 00000100 = 4

       5   d    7   6    c   e    2   d 
n = 01011101 01110110 11001110 00101101 
n % 8
n & 0x7

案例:

int n = 0x5d78ce2d;
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));
System.out.println(n % 8);
System.out.println(n & 0x7);
System.out.println(n % 16);
System.out.println(n & 0xf);

(2) 右移位运算 >>>

将2进制数字的整体向右移动,低位自动溢出,高位补0

                2   e    b   7    3   7    3   7  
n =          00101110 10110111 00110111 00110111
m = n>>>1    000101110 10110111 00110111 0011011 
k = n>>>2    0000101110 10110111 00110111 001101
g = n>>>8    00000000 00101110 10110111 00110111 

代码:

int n = 0x2eb73737;
int m = n>>>1;
int k = n>>>2;
int g = n>>>8;

https://gitee.com/robin_home/binary2209.git

案例:将一个int类型数据拆分为4个字节

例子:

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

代码:

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

(3) 或 |

运算规则:逻辑加法,有1则1

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

运算时候, 对齐位, 对应位计算

n          00000000 00000000 00000000 10111011
m          00000000 00000000 10111110 00000000
k =n|m     00000000 00000000 10111110 10111011

如上案例的意义:错位合并

int n = 0xbb;
int m = 0xbe00;
int k = m | n;

(4) 左移位运算

规则:2进制数字整体向左移动, 高位自动溢出, 低位自动补0

n         01011101 10010011 10111000 00111011
m = n<<1  1011101 10010011 10111000 001110110
k = n<<2  011101 10010011 10111000 0011101100
b2 =      00000000 00000000 00000000 10110111
b2<<8     00000000 00000000 10110111 00000000
int n = 0x5d93b83b;
int m = n<<1;
int k = n<<2;
int b2 = 0xb7;
System.out.println(Integer.toBinaryString(b2<<8));

将4个字节拼接为一个int(错位合并)

b1 =         00000000 00000000 00000000 00101110
b2 =         00000000 00000000 00000000 10110111
b3 =         00000000 00000000 00000000 00110111
b4 =         00000000 00000000 00000000 00110111
b1 << 24     00101110 00000000 00000000 00000000 
b2 << 16     00000000 10110111 00000000 00000000 
b3 << 8      00000000 00000000 00110111 00000000 
b4 << 0      00000000 00000000 00000000 00110111 
n = (b1<<24) | (b2<<16) | (b3<<8) | (b4<<0)    
int b1 = 0x2e;
int b2 = 0xb7;
int b3 = 0x37;
int b4 = 0x37;
int n = (b1<<24) | (b2<<16) | (b3<<8) | (b4<<0);

1.5 int 序列化

将一个int转换为byte数组, 是序列化

将一个字节数组转换为int数据,是反序列化

封装成方法

public class Demo10 {
    public static void main(String[] args) {
        int n = 0x6a7b9cef;
        System.out.println(Integer.toBinaryString(n));
        byte[] bytes = toBytes(n);
        System.out.println(Integer.toBinaryString(bytes[0] & 0xff));
        System.out.println(Integer.toBinaryString(bytes[1] & 0xff));
        System.out.println(Integer.toBinaryString(bytes[2] & 0xff));
        System.out.println(Integer.toBinaryString(bytes[3] & 0xff));
        int m = toInt(bytes);
        System.out.println(Integer.toBinaryString(m));
    }
    public static byte[] toBytes(int n){
        int b1 = (n >>> 24) & 0xff;
        int b2 = (n >>> 16) & 0xff;
        int b3 = (n >>> 8) & 0xff;
        int b4 = (n >>> 0) & 0xff;
        return new byte[]{(byte)b1, (byte)b2, (byte)b3, (byte)b4};
    }
    public static int toInt(byte[] bytes){
        int b1 = bytes[0] & 0xff; //  10111011
        int b2 = bytes[1] & 0xff;
        int b3 = bytes[2] & 0xff;
        int b4 = bytes[3] & 0xff;
        return (b1<<24) | (b2<<16) | (b3<<8) | (b4<<0);
    }
}

(1) 符号位扩展现象:

int n  =  -1
    //                                     11111111 11111111 11111111 11111111 
long l = n;
	// 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
n = -3;
    //                                     11111111 11111111 11111111 11111101
l = n;
    // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111101
n = 3;
    //                                     00000000 00000000 00000000 00000011
l = n;
    // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011
byte                              11111101
int       11111111111111111111111111111101
0xff      00000000000000000000000011111111
b & 0xff  00000000000000000000000011111101
public class Demo09 {
    public static void main(String[] args) {
        byte b = -3; //11111101
        //符号位扩展:负数时候 byte 转换为 int 高位补充24个1
        System.out.println(Integer.toBinaryString(b));
        //消除符号位扩展:利用掩码计算,消除高位1
        System.out.println(Integer.toBinaryString(b & 0xff));
    }
}

(2) 移位运算的数学意义

左移位一次,相当于数学乘以2

右移位一次,相当于数学除以2

(3) >> 数学右移位 和 >>> 逻辑右移位的区别

>> 正数时候, 高位补0; 负数时候,高位补1

>>> 无论正负高位补0, 不考虑数学结果,数字逻辑上向右移动

例子:

n           11111111 11111111 11111111 11011000  = -1-1-2-4-32 = -40
m = n>>1    111111111 11111111 11111111 1101100  = -1-1-2-16 = -20
k = n>>2    1111111111 11111111 11111111 110110  = -1-1-8 = -10
g = n>>3    11111111111 11111111 11111111 11011  = -5
h = n>>4    111111111111 11111111 11111111 1101  = -3 
x = n>>>1   011111111 11111111 11111111 1101100  = max-1-2-16
public class Demo11 {
    public static void main(String[] args) {
        System.out.println(20); //20
        System.out.println(20<<1); //40
        System.out.println(20<<2); //80
        System.out.println(20<<3); //160
    }
}
public class Demo12 {
    public static void main(String[] args) {
        int n = -40;
        System.out.println(Integer.toBinaryString(n));
        System.out.println(Integer.toBinaryString(n>>1));
        System.out.println(n>>1);
        System.out.println(Integer.toBinaryString(n>>2));
        System.out.println(n>>2);
        System.out.println(Integer.toBinaryString(n>>3));
        System.out.println(n>>3);
        System.out.println(Integer.toBinaryString(n>>4));
        System.out.println(n>>4);
        System.out.println(Integer.toBinaryString(n>>5));
        System.out.println(n>>5);
        System.out.println(Integer.toBinaryString(n>>>1));
        System.out.println(n>>>1);
        //ArrayList 扩容1.5倍
        //StringBuilder 扩容 1倍+2
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值