一、进制运算基本知识
1、进制运算的基础
Ⅰ 进制的概述
进制的定义:进位制是一种计数方式,也称进位计数法或位值计数法,
常见的进制:二进制、八进制、十进制、十六进制(因为计算机其实就是高低电平,0/1开关,所以计算机喜欢 2 进制,但是因为进制太小,表达一个大的数据的时候二进制表达就特别长,我们使用大进制位就可以解决这个问题,八进制、十六进制满足2的n次方的要求,自然就成为计算机表示数据的首选了);
Ⅱ 二进制运算的基础
注意:指数就是从右往左从0开始第几个数字的意思,前面的系数就是该位置对应的数值,底数就是当前的进制位数;
注意:这也是为什么 0.3 不能用计算机精确表示,而 0.5 可以的原因;

二、二进制数据的表示方法
1、有符号数和无符号数
使用一个符号位(约定数字位的最前面是符号位),0表示正数,1表示负数;
注意:这里如果用源码表示法的话,那么就出现了两个 0,即 +0 和 -0 ,例如只有两位来表示的话,00 即 +0,10 即 -0,但是其实不管是 +0 还是 -0 其实都是0,这样就存在歧义了,并且原码表示法进行运算的时候非常复杂,特别是两个操作数符号的时候;
- 判断两个操作数绝对值的大小;
- 使用绝对值大的数减去绝对值小的数;
- 对应符号值,以绝对值大的为准;
于是引入了补码和反码来使不同操作数的运算更加简单;
2、二进制的反码表示法
- 正数的补码和反码都是自己的本身;
- 负数的反码是将自己除过符号位以外取反;
3、二进制的补码表示法
使用正数来代替负数的方法,使用加法来代替减法,从而消除减法;
- 正数的补码和反码都是自己的本身;
- 负数的补码是将反码+1;
规律总结:
- 负数的反码等于原码除符号位外按位取反;
- 负数的补码等于反码+1;
4、小数的二进制补码表示
- 正小数的反码和补码都是自己;
- 负小数的补码等于反码+1;
三、二进制数据的计算
1、定点数与浮点数
- 小数点固定在某个位置的数称为定点数
如果我们需要表示的数既不是纯小数也不是纯整数,那我们就需要乘以比例因子以满足定点数保存格式(浮点数);
- 小数点位置不固定的数称为浮点数(比如 3.145625×10⁶ 也可以表示为 31456.25×10² 或者 3145.625×10³);
㈠ 浮点数的表示方法
Ⅰ 浮点数的表示格式
尾数必须使用纯小数,尾数可以为负数;

阶码的计算:左移一位阶码减一,右移阶码加一。
Ⅱ 浮点数的表示范围
Ⅲ 浮点数的规格化
- 尾数规定使用纯小数;
- 尾数最高位必须是1;(即必须是 0.1XXXXXX的形式)
上述阶码的算法是:x左移了三位,即阶码为 -3 ,3的二进制即为 11 ;
2、定点数的加减法运算
例1:A = -110010,B = 001101,求A+B ;A[补] = 1,001110B[补] = B[原] = 0,001101A[补] + B[补] = (A+B)[补] = 1,011011那么 A+B = (A+B)[补]-1的结果取反:A+B = 1,100101 = - 100101
例2:A = -0.1010010,B = 0.0110100,求 A+B ;A[补] = 1,1.0101110B[补] = B[原] = 0,0.01101001,1.01011100,0.0110100-----------------1,1.1100010A[补] + B[补] = (A+B)[补] = 1,1.1100010注意:十进制的时候借一位+10,二进制借一位+2(A+B)[反] = (A+B)[补]-1 = 1,1.1100001(A+B)[原] = (A+B)[反]取反 = 1,0.0011110 = -0.0011110例3:A = -10010000,B = -01010000,求 A+B ;A[补] = 1,01110000B[补] = 1,101100001,011100001,10110000--------------11,00100000 //去掉多出来的符号位进位 1,00100000A[补] + B[补] = (A+B)[补] = 1,00100000(A+B)[反] = 1,00011111(A+B)[原] = 1,11100000 = -11100000例4:A = -10010000,B = -11010000,求 A+B;A[补] = 1,01110000B[补] = 1,001100001,011100001,00110000------------------10,10100000 //去掉多出来的符号位进位 0,10100000A[补] + B[补] = (A+B)[补] = 0,10100000A+B = 10100000注意:A = -144,B = -208,但是 A+B = 160,这就是溢出,结果无效
判断溢出
- 双符号位判断法:单符号位表示变成双符号位:0 ==> 00,1 ==> 11,双符号位产生的进位丢失,结果的双符号位不同则表示溢出;
使用双符号位判断溢出(例4):11,0111000011,00110000------------------110,10100000 //去掉多出来的符号位进位,10,10100000,结果符号位不同,有溢出

例5:A = 11001000,B = -00110100,求 A-B;
A[补] = 0,11001000B[补] = 1,11001100(-B)[补] = 0,00110100A[补] - B[补] = A+(-B)[补]00,1100100000,00110100----------------00,11111100A+(-B)[补] = 0,11111100A - B = 111111100
注意:-B[补]等于B[补]连同符号位按位取反,末位+1;
3、浮点数的加减法运算
步骤:
- 对阶:使得两个浮点数的阶码一致,使得尾数可以进行运算(浮点数尾数运算简单,浮点数的位数实际小数位与阶码有关,所以阶码按小阶看齐大阶的原则对其,以便于运算);
- 尾数求和:使用补码进行运算,减法转化为加法运算;
- 尾数规格化:一般情况下都需要左移,但是当双符号位不一致的时候就需要右移(定点运算的溢出情况),右移的话则需要进行舍入操作;
- 舍入:0舍1入法(二进制的四舍五入法,比如S[补] = 10.10110111,s[补] = 11.01011011(1)(右移一位,有阶码的时候阶码要+1),我们右移之后把后面那个1挤没了,所以需要在这个结果上进行+1操作,即得到 11.01011100,0舍1入的意思就是后面被挤掉的那个数字是0还是1,是0就不管了,是1还要+1的),这种方法可以大大提高浮点数结果的精度,但是这样也会存在溢出问题 ;
- 溢出判断:例如s[补] = 01.11111111,这时候需要右移,得到 s[补] = 00.11111111(1),这个时候挤掉一个1,需要进行+1操作,得到 s[补] = 01.00000000,这个时候得到的结果双符号位还是不一致的,还需要右移,得到s[补] = 00.10000000(0),挤掉一个0,不用管,这个时候两次右移,阶码需要+2;
x = 0.1101 × 2⁰¹,y = (-0.1010)×2¹¹对阶:x = 0.001101×2¹¹,y = (-0.1010)×2¹¹,因为尾数值要对其,所以舍弃掉多余的尾数部分,x = 0.0011×2¹¹尾数求和:x[原] = 00.0011,x[补] = 00.0011;y[原] = 11.1010,y[补] = 11.0110;尾数和S = (x+y)[补] = 11.1001;尾数的规格化:S不满足规格化,需要左移1位:S = 11.0010左移之后,阶码需要-1,即由 11(3)变为 10(2)x+y[原] = -0.1110×2¹⁰
溢出判断
浮点数运算主要通过阶码的双符号位判断是否溢出,如果规格化之后,阶码双符号位不一致,则认为是溢出

4、浮点数的乘除法运算
- 乘法:阶码相加,尾数求积;
- 除法:阶码相减,尾数求商;
例1:x = 0.11010011 × 2¹¹⁰¹,y = 0.11101110 × 2⁰⁰⁰¹,假设阶码4位,尾数8位,求 x×yx×y = (0.11010011 × 0.11101110) × 2¹¹¹⁰= 0.11000100 × 2¹¹¹⁰
拉拉