进制的运算
1、十进制的对比分析
在十进制的数字中,每一列的权都是前一列的10倍,从右到左,每一列的权分别是1,10,100,1000…
看到十进制数的时候会发现其右下角有一个小小的10,这个小小的数称为十进制的c基,也就是说十进制的基是10
例:比如说:2345这个数是个十进制数
我们的一般就是个直接理解2345,这种思想是我们的常识思想,其实它真正的数字意义是在我们学习数字的时候刚开始的思维方式,
两个一千,三个一百,四个10,五个1,拿过来作为机器思想的描述就是:
每一位上的数字乘上他们对应位的权,再将结果加起来得到最终的数值
2、二进制
每一位上的数字只有0和1两个值,最后将多位合并起来就组成了一个二进制数
二进制的基是2
每一列的权从右到左分别是:1,2,4,8,16…,以此类推,也就是说个位的权是20,十位21…等等,同样通过机器的思想去理解
二进制就是:每一位上的数字(0/1)去乘上对应位的权(2的几次方)
1)二进制转换为十进制
个位权对应十进制:1
十位权对应十进制:2
百位权对应十进制:4
千位权对应十进制:8
…
例:1011
描述过来就是:1 * 1+1 * 2+0 * 4 + 1 * 8
通过二进制权对应的十进制的数来实现二进制到十进制的转化
2)十进制转二进制
比如说:给定十进制数84需要转换为二进制数
那么84中含的二进制的最大权就是64
所以64这一位上的数是1
然后 通过 84+64 = 20
64的下一位上的权是32,但是20<32,所以32这一位上的数就是0
32的下一位上的权是16,同时20>16,所以16这一位上的数就是1
以此类推
得到的 84》》》1010100
3、半字节,字节和字
对于二进制 8位一组称为字节,它能表示2^8 = 256 个数字,计算机中存储数据习惯于用字节作为单位,而不是用位作为单位。
4位的一组或者说半个字节称为半字节,能表示 2^4 = 16个数字(也就是一个十六进制数占用一个半字节),不常用,1024个字节称为1千字节(kilobyte ,KB),1024比特称为1千比特(kilobit,Kb或者Kbit),相似的MB,Mb称为兆字节,和兆比特,GB和Gb称为吉字节和吉比特。内存的容量一般用字节作为单位,但是信息传输率一般用比特/秒,作为单位。
对于微处理器来说,处理的一块数据称为字,字的大小取决于微处理器的结构。64位的处理器表示对64位的字进行操作,32位的处理器
对于32位的字进行处理。比较简单的微处理器也有8位或者16位字的
**最低有效位:**在一组位中,权为1的那位称其为最低有效位(lsb)
**最高有效位:**这组的位的另一端称为最高有效位(msb)
对于一个字来说可以通过十六进制来表示,这样就可以通过最低有效字节和最高有效字节来表示:
比如说:DEAFDAD8
最低有效字节是D8
最高有效字节是DE
4、二进制的溢出:
进行十进制的加法运算的时候经常会发生一个情况就是进位,比如说两个千位极的数相加就有可能生成一个万位级的数,但是正常在进行十进制的加法的时候并不会对这个有什么疑惑,因为十进制的数字加法一般是数字长度可变的,但是对于二进制的加法来说并不一样,一般在操作二进制数的时候都是操作的定长的数字。
比如说在两个四位的二进制数相加的时候,就有可能会产生一个五位的二进制数,但是用于接收这个结果的还是四位的长度,那么此时就会产生溢出(overflow),这个时候会将生成的第五位抛弃。从而产生了一个不正确的结果。
5、有符号的二进制数
二进制用于表示数当然是可以表示正负的,之前我们一直在考虑的是表示正数的无符号数(unsigned),那么就存在可以同时表示正数和复数的有符号数(signed),而用于表示有符号的二进制数的表示方法常用的有两种:
- 带符号的原码
- 带符号的补码
1)带符号的原码
将一个N位的二进制数进行区域设置,从左数的第一位,也就是最高位作为符号位,剩下的N-1位置为数值位,表示当前二进制数数值的绝对值。
其中符号位上:
- 0表示正数
- 1表示负数
存在的问题就是,普通的二进制数运算无法在带符号的原码下完成,比如说,-5(10)和5(10)相加的结果理应是0,但是用带符号的二进制原码去计算:
1101(2) + 0101(2) = 10010(2)
这样的计算结果很明显是错误且不合道理的。
表示范围:[-2(N-1)+1,2(N-1)-1]
通过带符号的原码表示的时候0有两个表示方法:+0和-0 。同一个数字有两种不同的表示方法可能会造成麻烦。
2)带符号的补码
对于补码来说最高位的权是-2(N-1),而不是2(N-1):
因为对于二进制的补码来说正数的最高位是0,0111…11(2) = 2^(N-1) -1,复数的最高位是1,1000…000(2) = -2(N-1)。所以说最高位的权表示的是-2^(N-1),相应的最高位就可以作为符号位,因为正数的最高位都是0,负数的最高位都是1.
而数值位在转换的时候也不一样:
无符号二进制数转换成有符号的二进制补码应该这样进行,首先将数扩一位,然后设置符号位,然后对对数据的每一位取反,然后在数据的最低位+1,因为二进制的补码表示0位0000000…000,具有唯一的标识方法,所以也可以进行普通的加法。
示例:
+2 的四位二进制补码表示为:0010
-2 的四位二进制补码表示为:1101 -> 1110
计算二进制补码负数的值:
将二进制数1001(2)转换为十进制数:
首先最高位是1,所以这个数是一个负数,然后每位取反 0110,加1 ,0111 ,这个数的十进制表达为7,所以就是-7(10)
将二进制数0010(2) 转换为十进制数:
首先最高位是0,所以这个数一定是一个正数,然后直接进行转换,所以这个数是2(10)
补码的加法运算:
计算 -2(10) + 1(20)
首先2 的二进制补码表达为0010,-2的二进制补码表达为1110(2),1的二进制表达为0001,1的二进制补码表达为0010(2),两数相加,补码表达为1111(0),转换成十进制数,先取反,0000(2),加一,0001,所以计算的结果为-1
计算-7(10) + 7(10)
首先7的二进制表达是0111,7的二进制补码表达是0111(2),-7的二进制补码表达是1001(2),相加等于10000(2),第五位抛弃,剩下的4位就是0000(2).
综上补码的运算有以下这么几条原则:
- 当进行N位的数据加法时,第N位的进位,也就是N+1位的结果会被丢弃,就是说,虽然我是进行4位的计算,就是说可以根据直接的数值计算的方式去计算符号位,但是最后这个数如果有第5位直接把第五位丢弃,剩下的数的值就是二进制补码计算最后的值
- 二进制的减法计算用补码去表示就是,将二进制的负数表示成补码,然后和第一个操作数的补码进行相加。
- 四位二进制数补码虽然是四位的,其实表示的范围是[-2(N-1),2[N-1]]
- 计算0的二进制补码的时候,就是将所有的二进制位取法,111…11(2),然后+1,最后舍弃掉最高位,因此0是唯一的,这和原码的系统不同,补码中0没有-0这一种表达方式,因此0的表达是唯一的,被认为是正数,因为它的符号位是0
3)带符号的反码
对于一个二进制数来说,如果这个二进制数是正数,那么它的反码就是它本身,但是如果这个二进制数是负数,那么它的反码就是在其原码的基础上,符号位不变,其余的各个位取反。
比如说:
1 的原码是 0001 ,它的反码是 0001
-1 的原码是1001, 它的反码是1110
两者相加:1 + (-1) = 0001 + 1110 = 1111(2) 然后取反 = 1000 = -0
对于反码的计算来说,结果的真值部分也就是数值部分是正确的,但是问题就出现在0这个特殊的数值上,它有100000和00000这样的两种表达方式,于是才出现了补码来解决这样的问题。
出现这样问题的原因是:
首先回顾一下人脑的计算方式,在人脑中不管是几进制都会根据符号判断加减运算,然后对真值区域进行加减,到那时对于计算机来说,加减乘除作为最基本的运算,要设计的尽可能的简单,让计算机去“辨别”符号位显然是一种非常复杂的设计,于是设计出能将符号位也参与运算的方法。根据运算原则的话,减去一个数相当于加上这个数的负数,所以计算机只有加法没有减法就会极大的遍历计算机运算的设计
4)小结
各种码之间的相互转换:
- 原码、补码、反码的正数表达都一样不需要转换
- 负数的原码转反码:符号位不变,真值位各位取反
- 负数的反码转原码:符号位不变,真值位各位取反
- 负数的原码转补码:符号位不变,真值位取反,末尾+1,舍掉溢出位
- 负数的补码转原码:符号位不变,真值位取反,末尾+1,舍掉溢出位
- 负数的反码转补码:末尾+1
- 负数的补码转反码:末尾-1(这里的反码是补码和反码指向的同一个原码的反码,而不是补码的反码)