0 前言

二进制的相干概念是学习数据存储、数据压缩、数据序列化的基石,只有真正搞清楚了二进制,能力逐渐深刻到算法源码,达到了解和复现的目标。

本文将介绍二进制和数据存储的相干概念(包含位、字节、高下位、大小端、原码、反码、补码、进制转换),以及二进制的位运算。

留神:本文解说偏实战,有些定义不够谨严,如需深入研究能够进一步浏览https://zhuanlan.zhihu.com/p/...

1 基本概念

1.1 位、字节

位(bit):计算机外部存储数据的最小单位。
字节(Byte):计算机存储容量(数据处理)的根本单位,1byte (字节)= 8 bit(位)。无符整型取值范畴0~255,有符整型取值范畴-128~127。

1byte = 8bit = 8二进制位 = 2个十六进制位

JAVA中数据类型的占用内存大小如图所示:

留神,string其实不属于根本数据类型,为便于比照将其放入字符型。

1.2 高位、低位、符号位

  • 高位:指在数据类型限定范畴内靠左的二进制位。
  • 低位:指在数据类型限定范畴内靠右的二进制位。
  • 符号位:指在数据类型限定范畴内最右边的一个二进制位,符号位为0示意负数,1示意正数。

【举例说明】
十进制数1的二进制为:0000 0001(最右边的0为符号位,从左往右对应的是高位向低位延长)
十进制数-1的二进制为:1111 1111(最右边的1为符号位,从左往右对应的是高位向低位延长)

【扩大】为什么-1的二进制位不是1000 0001呢?

详见https://zhuanlan.zhihu.com/p/...

1.3 大小端

对于一个字节序列,如何解析?到底是从左读还是从右读?正因为有了读写程序的差别,带来了两种不同的模式。

【定义】

  • 大端模式(Big-endian),是指数据的高字节位 保留在 内存的低地址中,而数据的低字节位 保留在 内存的高地址中。这样的存储模式有点儿相似于把数据当作字符串程序解决:地址由小向大减少,而数据从高位往低位放。和咱们”从左到右“浏览习惯统一。简言之,高位字节在前,低位字节在后
  • 小端模式(Little-endian),是指数据的高字节位 保留在 内存的高地址中,而数据的低字节位 保留在 内存的低地址中。这种存储模式将地址的高下位和数据位无效地联合起来,高地址局部权值高,低地址局部权值低,和咱们的逻辑办法统一。简言之,低位字节在前,高位字节在后

比方字节数据0x1A2B3C4D

内存的低位地址----------->内存的高位地址
大端模式:1A 2B 3C 4D
小端模式:4D 3C 2B 1A

【特点】

  • 大端:符号位在所示意的数据内存的第一个字节中,便于疾速判断数据的正负和大小(CPU做数值运算时从内存中依程序顺次从低位地址到高位地址取数据进行运算,大端就会最先拿到数据的(高字节的)符号位)。
  • 小端:CPU做数值运算时从内存中依程序顺次从低位地址到高位地址取数据进行运算,开始只管取值,最初刷新最高位地址的符号位就行,这样的运算形式会更高效一些。

目前咱们常见的CPU PowerPC、IBM是大端模式,x86是小端模式。ARM既能够工作在大端模式,也能够工作在小端模式,个别ARM都默认是小端模式。个别通信协定都采纳的是大端模式。

1.4 原码、反码、补码

暂不深究定义,从利用的角度,能够将原码、反码和补码分割在一起了解,就是计算相反数,即

原码的相反数=原码的补码=原码的反码(在原码根底上按位取反)+1

【举例说明】
原码=0000 0001(十进制为1)
反码=原码按位取反=1111 1110
补码=反码+1=1111 1111(十进制为-1)=-原码

若原码为-1,同样的运算能够失去其补码为1,因而,对于计算相反数而言,原码和补码是个绝对概念。

通过java程序验证:

import org.junit.Test;public class binaryTest {    public void print(int value){        System.out.println("value="+value+",其二进制串为(左侧的0省略):"+Integer.toBinaryString(value));    }    @Test    public void test(){        int i=-1;        print(i);  // 原码        print(~i); // 反码        print(~i+1);  // 补码}

【扩大】
如何用二进制示意浮点数?为何会有精度损失?

详见https://cloud.tencent.com/dev...

1.5 进制的示意与转换

JAVA中的进制示意及转换:

@Testpublic void convert(){    // 二进制示意--用0b    System.out.println(0b101);    // 十六进制示意--用0x    System.out.println(0x101);    // 二进制转十进制    System.out.println(Integer.valueOf("101",2));    // 十六进制转十进制    System.out.println(Integer.valueOf("a",16));    // 十进制转二进制    System.out.println(Integer.toBinaryString(10));    // 十进制转十六进制    System.out.println(Integer.toHexString(10));}

运行后果如下:

52575101010a

2 位运算

2.1 与、或、非、异或

假如A = 60,B = 13;它们的二进制格局示意将如下:

A = 0011 1100 B = 0000 1101 ----------------- A&B = 0000 1100 A|B = 0011 1101 A^B = 0011 0001 ~A  = 1100 0011

2.2 有符号左移<<

定义:a<<n,即a整体左移n位,高位抛弃,低位补零。
特点:每左移一位,相当于该数乘以2。
留神:当n=size-1时(size指位数,如1btye的size=8),符号位扭转,数值产生极其变动。

JAVA代码验证如下:

@Testpublic void zuoyi(){    int i=1;    System.out.println("================原始数据===============");    print(i);    System.out.println("================左移1位===============");    print(i<<1);    System.out.println("================左移31位===============");    print(i<<31);    int j =-1;    System.out.println("================原始数据===============");    print(j);    System.out.println("================左移1位===============");    print(j<<1);    System.out.println("================左移31位===============");    print(j<<31);}

运行后果如下:

================原始数据===============value=1,其二进制串为(左侧的0省略):1================左移1位===============value=2,其二进制串为(左侧的0省略):10================左移31位===============value=-2147483648,其二进制串为(左侧的0省略):10000000000000000000000000000000================原始数据===============value=-1,其二进制串为(左侧的0省略):11111111111111111111111111111111================左移1位===============value=-2,其二进制串为(左侧的0省略):11111111111111111111111111111110================左移31位===============value=-2147483648,其二进制串为(左侧的0省略):10000000000000000000000000000000

2.3 有符号右移>>

定义:a>>n,即a整体右移n位,低位抛弃,负数高位补零,正数高位补一。
特点:每右移一位,相当于该数除以2(向下取整)。
留神:当n大于原理论有效位数时,负数的最终后果为0,正数的最终后果为-1。

JAVA代码验证如下:

@Testpublic void youyi(){    int i=5;    System.out.println("================原始数据===============");    print(i);    System.out.println("================右移1位===============");    print(i>>1);    System.out.println("================右移2位===============");    print(i>>2);    System.out.println("================右移3位===============");    print(i>>3);    int j =-5;    System.out.println("================原始数据===============");    print(j);    System.out.println("================右移1位===============");    print(j>>1);    System.out.println("================右移2位===============");    print(j>>2);    System.out.println("================右移3位===============");    print(j>>3);}

运行后果如下:

================原始数据===============value=5,其二进制串为(左侧的0省略):101================右移1位===============value=2,其二进制串为(左侧的0省略):10================右移2位===============value=1,其二进制串为(左侧的0省略):1================右移3位===============value=0,其二进制串为(左侧的0省略):0================原始数据===============value=-5,其二进制串为(左侧的0省略):11111111111111111111111111111011================右移1位===============value=-3,其二进制串为(左侧的0省略):11111111111111111111111111111101================右移2位===============value=-2,其二进制串为(左侧的0省略):11111111111111111111111111111110================右移3位===============value=-1,其二进制串为(左侧的0省略):11111111111111111111111111111111

2.4 无符号右移>>>

定义:a>>>n,即a整体右移n位,低位抛弃,高位负数补零。
特点:若a为负数,则>>>与>>成果一样;若a为正数,挪动后均转为负数。

@Testpublic void youyi2(){    int i=5;    System.out.println("================原始数据===============");    print(i);    System.out.println("================右移1位===============");    print(i>>>1);    System.out.println("================右移2位===============");    print(i>>>2);    System.out.println("================右移3位===============");    print(i>>>3);    int j =-5;    System.out.println("================原始数据===============");    print(j);    System.out.println("================右移1位===============");    print(j>>>1);    System.out.println("================右移2位===============");    print(j>>>2);    System.out.println("================右移3位===============");    print(j>>>3);}

运行后果如下:

================原始数据===============value=5,其二进制串为(左侧的0省略):101================右移1位===============value=2,其二进制串为(左侧的0省略):10================右移2位===============value=1,其二进制串为(左侧的0省略):1================右移3位===============value=0,其二进制串为(左侧的0省略):0================原始数据===============value=-5,其二进制串为(左侧的0省略):11111111111111111111111111111011================右移1位===============value=2147483645,其二进制串为(左侧的0省略):1111111111111111111111111111101================右移2位===============value=1073741822,其二进制串为(左侧的0省略):111111111111111111111111111110================右移3位===============value=536870911,其二进制串为(左侧的0省略):11111111111111111111111111111

参考目录

[1] https://zhuanlan.zhihu.com/p/...
[2] https://zhuanlan.zhihu.com/p/...
[3] https://www.runoob.com/java/j...
[4] https://cloud.tencent.com/dev...
[5] https://zhuanlan.zhihu.com/p/...
[6] https://m.yisu.com/zixun/2158...