一.数据是什么

单位

等于bit

等于字节

等于字

bit

1

1/16

1/8

字节

8bit

1

1/2


16bit

2

1

在计算机中处理信息的最小单位是bit(位),bit不可再分且bit只有两个值

计算机把信息以一组或者一串bit的形式保存在存储器中,该形式被称为字节,一字节等于8位。计算机处理信息是以一串bit为基础。所以所有微处理器的字长都是8位的整数。计算机所处理的字节位数越多那么计算机的性能越好。

在计算机中数据以二进制的方式进行保存,无论是指令、数据、图像、视频还是什么都以二进制进行保存。
计算机保存数值的方法

数字在计算机中存储

计算机存储的数字表

类型

存储方法

译解方法

无符号整数

以二进制原码进行存储

直接将内存中的无符号整数的二进制编码转换为十进制

符号加绝对值

待定

有符号整数

二进制补码表示法

无符号整数的应用:

应用类型

解释

计数

计数不需要负数

寻址

地址都是从零开始,无符号整数适用

存储文本、图像、音频、视频

是以位的模式存储的,可以翻译为无符号整数

  计算机中的所有信息,都是用二进制进行表示。二进制的最小单位是“bit”,可以表示两种状态。给这两种状态赋予数字的意义就是“0” 和 “1”,赋予电位的意义就是“高电位”和“低电位”,赋予逻辑的意义就是“是”和“否”。位(bit)本身没有意义,只有当人去赋予意义或者进行解释的时候才会有意义。一个位只有两种状态,显然是不够用来表示各种各样不同的信息,所以就需要很多的位(bit)来进行组合。

  把位组合在一起,赋予某种解释或者意义就是编码。在计算机中数字的编码有三种重要的形式。无符号(unsigned)、补码(two's-complement)、浮点数(floating-point)。使用二进制编码的主要原因是因为底层的电路容易设计,并且比三进制电路便宜,是性价比的选择。

编码类型

作用

无符号编码

表示大于0或者等于0的整数

有编码

表示有符号整数,可以为正,可以为负的数字

浮点数编码

表示实数的科学计数法以2为基数的版本

  没有什么东西是无限的,所以编码的位数是有限的。它们取决于计算机的位数,而计算机的位数同样取决于性价比。一但数字太大,有限的位数无法表示的时候,就会出现溢出。就如C语言中的char类型一样,只有8位,也就是一字节。

\(2^8-1=255\)

  由于溢出的存在,在进行编程的时候,不得不考虑一下数据的范围,以防出现难以预料的错误。

  计算机中的编码,一定要注意机器的字长。比如在8086处理器中,字长为16位。

无符号编码:

  无符号编码,主要用来编码正整数,和计算机内存单元的地址。在二进制系统中,所有的位数都用来表示数值。比如有一个4位的二进制数。1010,在1010中的每一位,都是数值位。
比如整数6用二进制无符号的编码方式在16位处理器中进行表示。那么6的二进制码,就是6的二进制码,位数不足的时候要补零。

\[(6)_{10}=(0000000000000110)_{2} \]

  计算的方式就是对10进制的6转换为2进制的6。

转换的方法为:

\[6\div2=3······0 \]

\[3\div2=1······1 \]

\[1\div2=0······1 \]

  把余数从低到高排列 那么6的二进制就是 110。位数不足16位则补零,所以6的二进制无符号编码是0000000000000110。

有符号编码:

  在有符号编码中,有原码,反码,和补码这三种编码方式,但计算机中表示有符号数采用的是补码。

原码

  原码的编码最高位为符号位,其余位为数字位。组合是符号位+数值位 以16位处理器为例。

\[(6)_{10} = (0000000000000110)_{2} \]

\[(-6)_{10} = (1000000000000110)_{2} \]

\(~\){2^{15}-1}$

反码

  反码的定义是原码取反,规定正数的反码是正数本身,负数的反码是负数反码的取反,符号位不变。还是以16位处理器中,6来举例。

6的原码

\[(6)_{10} = (0000000000000110)_{2} \]

6的反码

\[(6)_{10} = (0000000000000110)_{2} \]

-6的原码

\[(-6)_{10} = (1000000000000110)_{2} \]

-6的反码

\[(-6)_{10} = (1111111111111001)_{2} \]

-6的反码变化中,符号位没有发生变化,但其它为进行了取反。

  任何一种工具的出现,一定是为了解决某个现有工具无法解决的问题。比如有符号编码的出现就是为了解决计算机中负数的表示,而反码的出现是为了解决计算机计算减法的问题。

我们来看一组运算二进制加法的运算,二进制加法的运算与十进制一样,唯一的差别在于十进制是逢十进一,而二进制是逢二进一。

  用原码进行编码的加法:

计算3+6=9 在16位cpu上。

\[(6)_{10} = (0000000000000110)_{2} \]

3的原码

\[(3)_{10} = (0000000000000011)_{2} \]

3+6

\[{{~~0000000000000011}} \]

\[{{+0000000000000110}} \]

\[{~—————————} \]

\[{{~~~0000000000001001}} \]

正确计算出来的结果等于9

\[(9)_{10} = (0000000000001001)_{2} \]

计算-6+3 = -3

\[{{~~1000000000000110}} \]

\[{{+0000000000000011}} \]

\[{~—————————} \]

\[{~~1000000000001001} \]

  计算出-6+3 = -9 这个结果明显是错误的,只有数值部分参与了运算,而符号部分没有。为了纠正这个错误,一是设计一种新的电路,可以让符号位参与运算,二是采用满足要求的编码方式。

  电路的设计是很麻烦的,多在cpu的运算器上设计一个电路,对应的成本就会增加很多。于是决定采用同种电路运算,所以反码出现了。

以下是反码编码的运算:

计算3+6 =9 反码的计算这个结果,很容易得出结果是正确的,因为正数的反码是本身。

计算-6+3 = -3

-6的反码:

\[(-6)_{10} = (1111111111111001)_{2} \]

用反码计算-6+3的结果

\[{{~~1111111111111001}} \]

\[{{+0000000000000011}} \]

\[{~—————————} \]

\[{~~~1111111111111100} \]

\({~~~1111111111111100}\)

在来计算一个 -6 + 6 = 0 计算出的16位二进制表示是 \({(1111111111111111)_2}\)

\({(0000000000000000)_2}\) 这好像有点不太对,因为1的反码编码是\({(0000000000000001)_2}\)而不是 \({(0000000000000000)_2}\)

最后一种编码方式是补码编码。

补码

计算机对有符号数采用的编码方式是补码的编码方式。虽然C语言标准并没有要求用补码来表示有符号整数,但几乎所有的机器是这样做的。意思是,几乎所有机器,对有符号数采用的都是补码的编码方式。

这意味着,在计算机低层。所有的有符号运算,都是基于补码的运算。

补码的定义:

对于正数而言,正数的补码就是原码。

对于负数而言,负数的补码是反码+1。

比如 -6的补码

先要16位知-6的反码:

\[(-6)_{10} = (1111111111111001)_{2} \]

然后加一个 1

就是

\[(-6)_{10} = (1111111111111010)_{2} \]

就可以求出-6的补码为\((1111111111111010)_{2}\)