咱们都知道,计算机的底层都是使用二进制数据进行数据流传输的,那么为何会使用二进制表示计算机呢?或者说,什么是二进制数呢?在拓展一步,如何使用二进制进行加减乘除?二进制数如何表示负数呢?本文将一一为你揭晓。编程
咱们你们知道,计算机内部是由IC电子元件组成的,其中 CPU
和 内存
也是 IC 电子元件的一种,CPU和内存图以下编程语言
CPU 和 内存使用IC电子元件做为基本单元,IC电子元件有不一样种形状,可是其内部的组成单元称为一个个的引脚。有人说CPU 和 内存内部都是超大规模集成电路,其实IC 就是集成电路(Integrated Circuit)。ui
IC元件两侧排列的四方形块就是引脚,IC的全部引脚,只有两种电压: 0V
和 5V
,IC的这种特性,也就决定了计算机的信息处理只能用 0 和 1 表示,也就是二进制来处理。一个引脚能够表示一个 0 或 1 ,因此二进制的表示方式就变成 0、一、十、十一、100、101等,虽然二进制数并非专门为 引脚 来设计的,可是和 IC引脚的特性很是吻合。编码
计算机的最小集成单位为 位
,也就是 比特(bit)
,二进制数的位数通常为 8位、16位、32位、64位,也就是 8 的倍数,为何要跟 8 扯上关系呢? 由于在计算机中,把 8 位二进制数称为 一个字节, 一个字节有 8 位,也就是由 8个bit构成。设计
为何1个字节等于8位呢?由于 8 位可以涵盖全部的字符编码,这个记住就能够了。code
字节是最基本的计量单位,位是最小单位。blog
用字节处理数据时,若是数字小于存储数据的字节数 ( = 二进制的位数),那么高位就用 0 填补,高位和数学的数字表示是同样的,左侧表示高位,右侧表示低位。好比 这个六位数用二进制数来表示就是 100111
,只有6位,高位须要用 0 填充,填充完后是 00100111
,占一个字节,若是用 16 位表示 就是 0000 0000 0010 0111
占用两个字节。图片
咱们通常口述的 32 位和 64位的计算机通常就指的是处理位数,32 位一次能够表示 4个字节,64位一次能够表示8个字节的二进制数。内存
咱们通常在软件开发中用十进制数表示的逻辑运算等,也会被计算机转换为二进制数处理。对于二进制数,计算机不会区分他是 图片、音频文件仍是数字,这些都是一些数据的结合体。开发
那么什么是二进制数呢?为了说明这个问题,咱们先把 00100111
这个数转换为十进制数看一下,二进制数转换为十进制数,直接将各位置上的值 * 位权便可,那么咱们将上面的数值进行转换
也就是说,二进制数表明的 00100111
转换成十进制就是 39,这个 39 并非 3 和 9 两个数字连着写,而是 3 * 10 + 9 * 1,这里面的 10 , 1
就是位权,以此类推,上述例子中的位权从高位到低位依次就是 7 6 5 4 3 2 1 0
。这个位权也叫作次幂,那么最高位就是2的7次幂,2的6次幂 等等。二进制数的运算每次都会以2为底,这个2 指得就是基数,那么十进制数的基数也就是 10 。在任何状况下位权的值都是 数的位数 - 1,那么第一位的位权就是 1 - 1 = 0, 第二位的位权就睡 2 - 1 = 1,以此类推。
那么咱们所说的二进制数其实就是 用0和1两个数字来表示的数,它的基数为2,它的数值就是每一个数的位数 * 位权再求和获得的结果,咱们通常来讲数值指的就是十进制数,那么它的数值就是 3 * 10 + 9 * 1 = 39。
在了解过二进制以后,下面咱们来看一下二进制的运算,和十进制数同样,加减乘除也适用于二进制数,只要注意逢 2 进位便可。二进制数的运算,也是计算机程序所特有的运算,所以了解二进制的运算是必需要掌握的。
首先咱们来介绍移位
运算,移位运算是指将二进制的数值的各个位置上的元素坐左移和右移操做,见下图
上述例子中仍是以 39 为例,咱们先把十进制的39 转换为二进制的 0010 0111
,而后向左移位 <<
一个字节,也就变成了 0100 1110
,那么再把此二进制数转换为十进制数就是上面的78, 十进制的78 居然是 十进制39 的2倍关系。咱们在让 0010 0111
左移两位,也就是 1001 1100
,得出来的值是 156,至关于扩大了四倍!
所以你能够得出来此结论,左移至关因而数值扩大的操做,那么右移 >>
呢?按理说右移应该是缩小 1/2,1/4 倍,可是39 缩小二倍和四倍不就变成小数了吗?这个怎么表示呢?请看下一节
刚才咱们没有介绍右移的状况,是由于右移以后空出来的高位数值,有 0 和 1 两种形式。要想区分何时补0何时补1,首先就须要掌握二进制数表示负数
的方法。
二进制数中表示负数值时,通常会把最高位做为符号来使用,所以咱们把这个最高位看成符号位。 符号位是 0 时表示正数
,是 1 时表示 负数
。那么 -1 用二进制数该如何表示呢?可能不少人会这么认为: 由于 1 的二进制数是 0000 0001
,最高位是符号位,因此正确的表示 -1 应该是 1000 0001
,可是这个答案真的对吗?
计算机世界中是没有减法的,计算机在作减法的时候其实就是在作加法,也就是用加法来实现的减法运算。好比 100 - 50 ,其实计算机来看的时候应该是 100 + (-50),为此,在表示负数的时候就要用到二进制补数
,补数就是用正数来表示的负数。
为了得到补数
,咱们须要将二进制的各数位的数值所有取反,而后再将结果 + 1 便可,先记住这个结论,下面咱们来演示一下。
具体来讲,就是须要先获取某个数值的二进制数,而后对二进制数的每一位作取反操做(0 ---> 1 , 1 ---> 0),最后再对取反后的数 +1 ,这样就完成了补数的获取。
补数的获取,虽然直观上不易理解,可是逻辑上却很是严谨,好比咱们来看一下 1 - 1 的这个过程,咱们先用上面的这个 1000 0001
(它是1的补数,不知道的请看上文,正确性先无论,只是用来作一下计算)来表示一下
奇怪,1 - 1 会变成 130 ,而不是0,因此能够得出结论 1000 0001
表示 -1 是彻底错误的。
那么正确的该如何表示呢?其实咱们上面已经给出结果了,那就是 1111 1111
,来论证一下它的正确性
咱们能够看到 1 - 1 其实实际上就是 1 + (-1),对 -1 进行上面的取反 + 1 后变为 1111 1111
, 而后与 1 进行加法运算,获得的结果是九位的 1 0000 0000
,结果发生了溢出
,计算机会直接忽略掉溢出位,也就是直接抛掉 最高位 1 ,变为 0000 0000
。也就是 0,结果正确,因此 1111 1111
表示的就是 -1 。
因此负数的二进制表示就是先求其补数,补数的求解过程就是对原始数值的二进制数各位取反,而后将结果 + 1,
固然,结果不为 0 的运算一样也能够经过补数求得正确的结果。不过,有一点须要注意,当运算结果为负的时候,计算结果的值也是以补数的形式出现的,好比 3 - 5 这个运算,来看一下解析过程
3 - 5 的运算,咱们按着上面的思路来过一遍,计算出来的结果是 1111 1110
,咱们知道,这个数值确定表示负数,可是负数没法直接用十进制表示,须要对其取反+ 1,算出来的结果是 2,由于 1111 1110
的高位是 1,因此最终的结果是 -2。
编程语言的数据类型中,有的能够处理负数,有的不能够。好比 C语言中不能处理负数的 unsigned short
类型,也有能处理负数的short
类型 ,都是两个字节的变量,它们都有 2 的十六次幂种值,可是取值范围不同,short 类型的取值范围是 -32768 - 32767 , unsigned short 的取值范围是 0 - 65536。
仔细思考一下补数的机制,就能明白 -32768 比 32767 多一个数的缘由了,最高位是 0 的正数有 0 ~ 32767 共 32768 个,其中包括0。最高位是 1 的负数,有 -1 ~ -32768 共 32768 个,其中不包含0。0 虽然既不是正数也不是负数,可是考虑到其符号位,就将其归为了正数。
在了解完补数后,咱们从新考虑一下右移这个议题,右移在移位后空出来的最高位有两种状况 0 和 1
。当二进制数的值表示图形模式而非数值时,移位后须要在最高位补0,相似于霓虹灯向右平移的效果,这就被称为逻辑右移
。
将二进制数做为带符号的数值进行右移运算时,移位后须要在最高位填充移位前符号位的值( 0 或 1)。这就被称为算数右移
。若是数值使用补数表示的负数值,那么右移后在空出来的最高位补 1,就能够正确的表示 1/2,1/4,1/8
等的数值运算。若是是正数,那么直接在空出来的位置补 0 便可。
下面来看一个右移的例子。将 -4 右移两位,来各自看一下移位示意图
如上图所示,在逻辑右移的状况下, -4 右移两位会变成 63
, 显然不是它的 1/4,因此不能使用逻辑右移,那么算数右移的状况下,右移两位会变为 -1
,显然是它的 1/4,故而采用算数右移。
那么咱们能够得出来一个结论:左移时,不管是图形仍是数值,移位后,只须要将低位补 0 便可;右移时,须要根据状况判断是逻辑右移仍是算数右移。
下面介绍一下符号扩展:将数据进行符号扩展是为了产生一个位数加倍、但数值大小不变的结果,以知足有些指令对操做数位数的要求,例如倍长于除数的被除数,再如将数据位数加长以减小计算过程当中的偏差。
以8位二进制为例,符号扩展就是指在保持值不变的前提下将其转换成为16位和32位的二进制数。将0111 1111
这个正的 8位二进制数转换成为 16位二进制数时,很容易就可以得出0000 0000 0111 1111
这个正确的结果,可是像 1111 1111
这样的补数来表示的数值,该如何处理?直接将其表示成为1111 1111 1111 1111
就能够了。也就是说,无论正数仍是补数表示的负数,只须要将 0 和 1 填充高位便可。
掌握逻辑和运算的区别是:将二进制数表示的信息做为四则运算的数值来处理就是算数
,像图形那样,将数值处理为单纯的 0
和 1
的罗列就是逻辑
计算机可以处理的运算,大致可分为逻辑运算和算数运算,算数运算
指的是加减乘除四则运算;逻辑运算
指的是对二进制各个数位的 0 和 1分别进行处理的运算,包括逻辑非(NOT运算)、逻辑与(AND运算)、逻辑或(OR运算)和逻辑异或(XOR运算)四种。
逻辑非
指的是将 0 变成 1,1 变成 0 的取反操做逻辑与
指的是"两个都是 1 时,运算结果才是 1,其余状况下是 0"逻辑或
指的是"至少有一方是 1 时,运算结果为 1,其余状况下运算结果都是 0"逻辑异或
指的是 "其中一方是 1,另外一方是 0时运算结果才是 1,其余状况下是 0"掌握逻辑运算的窍门,就是要摒弃二进制数表示数值这一个想法。你们不要把二进制数表示的值看成数值,应该把它当作是 开关上的 ON/OFF
。