G
N
I
D
A
O
L

【组成原理-数据】定点数的编码与运算

0 必知的常用数

  • (128)10 = (7F)16 = 27
  • (256)10 = (FF)16 = 28
  • (1024)10 = (400)16 = 210
  • (32768)10 = (FFFF)16 = 215
  • (65536)10 = (10000)16 = 216
  • (2147483648)10 = 231
  • (4294967296)10 = 232

1 定点数的编码

1.1 编码的种类

定点数编码有四种:

  • 原码:最高位表示真值的符号(1 表示负,0 表示正),其余各位表示真值的绝对值

【注 1】设原码字长为 n(即有 n 位),则原码整数的表示范围为-(2n-1-1) ≤ x ≤ +(2n-1-1)

【注 2】设原码字长为 n(即有 n 位),则原码小数的表示范围为-(1-2-(n-1)) ≤ x ≤ +(1-2-(n-1))

【注 3】原码全 0,对应真值的最小值-(2n-1);原码全 1,对应真值的最大值+(2n-1-1)

【注 4】0 的表示不唯一,分正负零(0,000,0000 和 1,000,0000)

  • 反码:正数的反码与原码一样,负数的反码其数值部分全部取反

【注 1】设反码字长为 n(即有 n 位),则反码整数的表示范围为-(2n-1-1) ≤ x ≤ +(2n-1-1)

【注 2】设反码字长为 n(即有 n 位),则反码小数的表示范围为-(1-2-(n-1)) ≤ x ≤ +(1-2-(n-1))

【注 3】反码全 0,对应真值的最小值-(2n-1);反码全 1,对应真值的最大值+(2n-1-1)

【注 4】0 的表示不唯一,分正负零(0,000,0000 和 1,111,1111)

  • 补码(带符号整数):正数的补码与反码一样,负数的补码等于反码加 1

【注 1】设补码字长为 n(即有 n 位),则补码整数的表示范围为-(2n-1) ≤ x ≤ +(2n-1-1)

【注 2】设补码字长为 n(即有 n 位),则补码小数的表示范围为-1 ≤ x ≤ +(1-2-n)

【注 3】补码全 0,对应真值的最小值-(2n-1);补码全 1,对应真值的最大值+(2n-1-1)

【注 4】0 的表示唯一(0,000,0000);无论补码有多少位,只要所有位都为 1,那么表示的真值为 -1

【注 5】若补码的符号位相同,则数值位越大码值越大

  • 移码:真值基础上加上一个偏置常数(取 2n

【注 1】设移码字长为 n(即有 n 位),则移码整数的表示范围为-(2n-1) ≤ x ≤ +(2n-1-1)

【注 2】移码全 0,对应真值的最小值-2n;移码全 1,对应真值的最大值+(2n-1)

【注 3】0 的表示唯一(1,000,0000)

【注 4】移码保持了数据原有的大小顺序,移码大真值就大,移码小真值就小

真值 补码 移码
-128 1000,0000 0000,0000
-127 1000,0001 0000,0001
-126 1000,0010 0000,0010
... ... ...
-2 1111,1110 0111,1110
-1 1111,1111 0111,1111
0 0000,0000 1000,0000
1 0000,0001 1000,0001
2 0000,0010 1000,0010
... ... ...
125 0111,1101 1111,1101
126 0111,1110 1111,1110
127 0111,1111 1111,1111

1.2 编码的转换

  • 正数:原码 --(不用变)--> 反码 --(不用变)--> 补码 --(符号位取反)--> 移码
  • 负数:原码 --(数值部分取反)--> 反码 --(直接加 1)--> 补码 --(符号位取反)--> 移码
  • 负数:原码 <--(从右往左找第一个“1”,“1”左边所有数值位取反)--> 补码
  • 补码转真值:最高的符号位有负值加权,例:[1,000,0011] = (-27+21+20)10 = (-125)10

【例 1】(-100)10 的编码转换(默认 8 位字长)

先化为十六进制,再转换为二进制:(100)10 = (64)16 = (0110,0100)2

(1)原码:1,110,0100

(2)反码:1,001,1011

(3)补码:1,001,1100

(4)移码:0,001,1100

【例 2】(1,000,1101)2(默认 8 位字长),若为(1)原码;(2)反码;(3)补码;(4)移码,求对应真值?

(1)原码:1,000,1101 --> 转换为十六进制:1(-),000(0),1101(13) --> 转换为十进制:(-13)10

(2)反码:1,000,1101 --> 原码:1,111,0010 --> 转换为十六进制:1(-),111(7),0010(2) --> 转换为十进制:-(16*7+2)10 = (-114)10

(3)补码:1,000,1101 --> 原码:1,111,0011 --> 转换为十六进制:1(-),111(7),0011(3) --> 转换为十进制:-(16*7+3)10 = (-115)10

(4)移码:1,000,1101 --> 补码:0,000,1101 --> 转换为十六进制:0(+),000(0),1101(13) --> 转换为十进制:(+13)10

补充:负数补码和原码的转换技巧(几秒钟内迅速转换一个 32 位二进制数!)

下面教大家一个小技巧:有时候需要对一个长达 16 位或 32 位的负定点数进行原码和补码的转换,如果一位位进行取反,这就显得太过麻烦了。实际上有非常迅速地转换方法

我们注意到十六进制与二进制之间的联系,即一位十六进制数正好对应四位二进制数,所以同时变换四位二进制数相当于变换一位十六进制数,这样一个 16 位数只需变换 4 次即可。变换操作的实质是取反操作,见下表,容易发现,取反前和取反后的值加起来恒等于 15,所以我们看到一位十六进制数就可以立即说出它取反后的结果。

取反前 取反后
0(0000) F(1111)
1(0001) E(1110)
2(0010) D(1101)
3(0011) C(1100)
4(0100) B(1011)
5(0101) A(1010)
6(0110) 9(1001)
7(0111) 8(1011)
8(1000) 7(0111)
9(1001) 6(1011)
A(1010) 5(0101)
B(1011) 4(0100)
C(1100) 3(0011)
D(1101) 2(0010)
E(1110) 1(0001)
F(1111) 0(0000)

【例 3】一个 16 位补码 0x8F0A 的原码是多少?

【解】根据补码转原码规则,先找到该补码的第一个“1”在哪里,它所在的十六进制位数不能用上述方法,需要特殊处理。显然在最低位的“A”处出现第一个“1”,写出二进制形式:1010,按照转换规则得到:0110,即十六进制的 6。

剩余三位全部取反,“8F0”取反后为“70F”,所以对应无符号原码为 0x70F6。而对于有符号原码,最高位为符号位,答案应为 0x80F6。

其实一开始的特殊处理也是可以直接口答结果,因为容易发现,特殊处理前和特殊处理后的值相加恒等于 16。见下表:

特殊处理前 特殊处理后
0(0000) 不需要处理
1(0001) F(1111)
2(0010) E(1110)
3(0011) D(1101)
4(0100) C(1100)
5(0101) B(1011)
6(0110) A(1010)
7(0111) 9(1001)
8(1000) 8(1000)
9(1001) 7(0111)
A(1010) 6(0110)
B(1011) 5(0101)
C(1100) 4(0100)
D(1101) 3(0011)
E(1110) 2(0010)
F(1111) 1(0001)

【例 4】一个 32 位补码 0xFFFF FFDF 对应真值是多少?

【解】最低位的“F”需要特殊处理,转换为“1”(16 减 15)。剩余七位全部取反,“FFFF FFD”取反后为“0000 002”,所以对应原码为 0x0000 0021,真值为 -(2 * 16 + 1) = -33。

【例 5】真值 -98 转化为 32 位补码是多少?

【解】将 98 化为十六进制数 0x62,扩展成 32 位原码 0x0000 0062。最低位的“2”需特殊处理,转换为“E”(16 减 2)。剩余七位全部取反,“0000 006”取反后为“FFFF FF9”,所以对应补码为 0xFFFF FF9E。

【总结】负数补码和原码的转换技巧

前提:补码表示的是真值是负数!

(1)找到需要特殊处理的最低位,该位需要特殊处理,特殊处理前和特殊处理后的值相加恒等于 16;

(2)剩余的高位进行取反操作,取反前和取反后的值相加恒等于 15。

1.3 C 语言的强制转换

  • 相同字长下,有符号数与无符号数的转换:保持位值不变,仅改变解释位值的方式
  • 长字长转换短字长:多余的高位直接丢弃,低位直接赋值
  • 短字长转换长字长:无符号情况下,扩展的高位部分用 0 填充;有符号情况下,扩展的高位部分用原数字符号填充
  • C 语言中赋值和判断也会出现强制类型转换,常见转换路径:char-->int-->long-->double 和 float-->double(范围和精度从小到大,转换过程没有损失)

【例 1】16 位补码 0x8FA0 扩展为 32 位是 0xFFFF 8FA0。

【例 2】假设变量 i、f 和 d 的数据类型分别为 int、float 和 double,其中 f = 1.5678E3,d = 1.5E100,则下列是否为“真”?

  • i==(int)(float)i:转换过程为 int-->float-->int,没有精度损失,结果为真
  • f==(float)(int)f:转换过程为 float-->int-->float,转换的第一步存在精度损失,结果为假
  • f==(float)(double)f:转换过程为 float-->double-->float,没有精度损失,结果为真
  • d==(double)(float)d:转换过程为 double-->float-->double,转换的第一步存在精度损失,结果为假
  • (d+f)-f==f:浮点数运算,f 需要先转换为 double 类型,再和 d 进行对阶,对阶过程中 f 产生精度损失,结果为假

补充:不同机器下的数据类型长度

类型 16 位机器 32 位机器 64 位机器
char 8 8 8
short 16 16 16
int 16 32 32
long 32 32 32
long long 64 64 64
float 16 32 32
double 64 64 64

2 定点数的运算

2.1 定点数的移位

移位有三种:算术移位、逻辑移位、循环移位。

2.1.1 算术移位(有符号数)

【规则】

  • 算术移位过程中,符号位均保持不变
  • 正数的算术移位:原码、补码、反码算术移位,空位添 0
  • 负数原码的算术移位:用 0 占据空位

负数的原码数值部分与真值相同,因此移位时符号位不变,其余空位添 0

  • 负数反码的算术移位:空位添 1

负数的反码数值部分与负数的原码相反,因此移位时其余空位添相反的数,即为 1

  • 负数补码的算术移位:算术左移,低位空位添 0;算术右移,高位空位添 1

负数的原码转补码,从右往左(从低到高)找到第一个“1”,这个“1”的左边(符号位除外)与原码相反,故空位添相反的数,即为 1;右边与原码相同,故空位仍添 0

【例】负数补码的算术移位

算术右移 1 位:1,110,0110 >> 1 = 1,111,0011

算术右移 2 位:1,110,0110 >> 2 = 1,111,1001

算术左移 1 位:1,110,0110 << 1 = 1,100,1100

算术左移 2 位:1,110,0110 << 1 = 1,001,1000

【注】补码正数的符号位为 0,左移最高位为 0 时,数据不会丢失;负数的符号位为 1,左移最高位为 1 时,数据不会丢失。

2.1.2 逻辑移位(无符号数)

【规则】

  • 逻辑移位将操作数视为无符号数
  • 逻辑左移:高位丢弃,低位添 0
  • 逻辑右移:低位丢弃,高位添 0

2.1.3 循环移位

【规则】

  • 不带进位的循环左移:高位溢出的数填充回低位,且高位溢出的数还要存入进位标志位 CF
  • 不带进位的循环右移:低位溢出的数填充回高位,且低位溢出的数还要存入进位标志位 CF
  • 带进位的循环左移:CF 的值填充回低位,且高位溢出的数还要存入进位标志位 CF
  • 带进位的循环右移:CF 的值填充回高位,且低位溢出的数还要存入进位标志位 CF
  • 循环移 n 位:相当于进行 n 次的循环移 1 位
  • 一般用途:将数据的低字节数据与高字节数据互换位置

【例】一个 8 位寄存器内的数值为 0100,1011,进位标志位 CF=1,若(1)带进位循环左移一位;(2)带进位循环右移一位;(3)不带进位循环左移一位;(4)不带进位循环右移一位,结果是多少?

【注】括号内的英文表示该数值位是从 CF、数值的高位(HIGH)还是数值的低位(LOW)移进来的。

(1)带进位循环左移一位:100,1011,1 (CF);CF = 0 (HIGH)

(2)带进位循环右移一位:1 (CF),0100,101;CF = 1 (LOW)

(3)不带进位循环左移一位:100,1011,0 (HIGH);CF = 0 (HIGH)

(4)不带进位循环右移一位:1 (LOW),0100,101;CF = 1 (LOW)

2.2 定点数的加减法

2.2.1 补码的加减法

  • 加法运算:补码直接相加
  • 减法运算:被减数-减数,减数转换为其负数的补码,转换为加法运算进行

【例】A = 15,B = 28,计算 [A+B],[A-B]

转换为二进制:A = (15)10 = (000,1111)2, B = (28)10 = (001,1100)2

[A]= 0,000,1111, [B]= 0,001,1100

[A]= 0,000,1111, [B]= 0,001,1100, [-B]= 1,110,0100

[A+B] = 0,000,1111 + 0,001,1100 = 0,010,1011 = (+43)10

[A-B] = 0,000,1111 + 1,110,0100 = 1,111,0011 = (-13)10

2.2.2 补码加减溢出的判别

发生溢出的情况:

  • 两个同号数相加,得到的结果却异号
  • 两个异号数相减,得到的结果与被减数异号

【模 2 补码】有一个符号位的补码,即正常的补码。

【模 4 补码(变形补码)】有两个符号位 S1S2 的补码,“00”表示正数,“11”表示负数,如:

  • -3:补码:1,101;变形补码:11,101
  • +3:补码:0,011;变形补码:00,011

若两个符号位不同,“01”表示正溢出,“10”表示负溢出,最高位符号位表示真正的符号。

实际情况下,存储每个变形补码仅需一个符号位,因为无论正数还是负数,两个符号位都是一样的,只有在运算时才会出现不一样的情况。

  • 溢出标志位 OF = 1 时,说明发生了溢出
  • OF = 最高位(即符号位)进位 ⊕ 次高位(即数值的最高位)进位 = S1⊕ S2
  • OF 位仅对于有符号数有意义!

即:最高位和次高位,一个有进位,另一个没有进位,若它们的异或值是 1,则结果就有溢出。

补码加减溢出的相关例题

【例 1】溢出的例子:0100,0000 + 0100,0000 = 1000,0000

列竖式:

运算 溢出 操作数
. 0100 0000
(+) 0100 0000
. 1000 0000
  • 加黑体数位为最高位,最高位没有产生进位
  • 斜体数位为次高位,次高位产生了进位
  • 因此结果溢出

【例 2】溢出的例子:1000,0000 + 1000,0000 = 0000,0000

列竖式:

运算 溢出 操作数
. 1000 0000
(+) 1000 0000
. 1 0000 0000
  • 加黑体数位为最高位,最高位产生了进位
  • 斜体数位为次高位,次高位没有产生进位
  • 因此结果溢出

【例 3】没有溢出的例子:1111,1111 + 0001,0000 = 0000,1111

列竖式:

运算 溢出 操作数
. 1111 1111
(+) 0001 0000
. 1 0000 1111
  • 加黑体数位为最高位,最高位产生了进位
  • 斜体数位为次高位,次高位产生了进位
  • 因此结果没有溢出
补充:使用 SF 和 OF 判断补码大小关系

SF 位:补码为非负,SF = 0;补码为负,SF = 1

cmp ah, bh为例,a-b 测试:

OF OF 说明 SF SF 说明 结果
0 没有溢出,逻辑上真正结果的正负=实际结果的正负 1 实际结果为负 逻辑上真正的结果为负,(ah)<(bh)
1 有溢出,逻辑上真正结果的正负≠实际结果的正负 1 实际结果为负 逻辑上真正的结果为非负,(ah)≥(bh)
1 有溢出,逻辑上真正结果的正负≠实际结果的正负 0 实际结果为非负 逻辑上真正的结果为负,(ah)<(bh)
0 没有溢出,逻辑上真正结果的正负=实际结果的正负 0 实际结果为非负 逻辑上真正的结果为非负,(ah)≥(bh)

2.2.3 进/借位的判别

  • CF 位仅对无符号数有意义!
  • 加法:CF = 最高位进位输出
  • 减法:CF = 最高位进位输出取反

2.3 定点数的乘除法

2.3.1 定点数乘除法的技巧

在介绍定点数乘除法规则之前,先讲一个相关技巧:当一个数乘以或除以 2 的幂次方的数时,可以使用移位运算,具体原理就不细说了。

【规则】

(1)补码:当二进制数 A 乘以 2n 时,二进制数 A 算术左移 n 位;当二进制数 A 除以 2n 时,二进制数 A 算术右移 n 位。

(2)原码:当二进制数 A 乘以 2n 时,二进制数 A 逻辑左移 n 位;当二进制数 A 除以 2n 时,二进制数 A 逻辑右移 n 位。

【例 1】32 位补码乘法运算 B052H * 0008H = ?

【解】十六进制 B052H 转成二进制:1011 0000 0101 0010,因为 8 = 23,所以需算数左移三位,即 1 0000 0101 0010 000,整理一下得到:1000 0010 1001 0000,即十六进制的 8290H(可以发现结果溢出,因为数值部分高三位都被丢弃了,原结果应为 D8290H)。

【例 2】32 位补码乘法运算 B052H / 0008H = ?

【解】十六进制 B052H 转成二进制:1011 0000 0101 0010,因为 8 = 23,所以需算数右移三位,即 111 1011 0000 0101 0,整理一下得到:1111 0110 0000 1010,即十六进制的 F60AH。

2.3.2 乘法的溢出判断

  • 无符号乘法:n 位 x n 位,用 2n 位保存中间运算结果,取后 n 位为最终结果。仅当前 n 位都是 0 时不溢出。
  • 有符号乘法:n 位 x n 位,用 2n 位保存中间运算结果,取后 n 位为最终结果。仅当前 n+1 位都是 0 或 1 时不溢出。

【例】32 位补码 7FFF,FFFFH 乘 2 的 64 位中间乘积结果是多少?最终结果需存入 32 位寄存器中,请问溢出了吗?

【解】中间结果是 0000,0000,FFFF,FFFEH,由于前 33 位不全为 0 或 1,所以发生了溢出。

2.3.3 原码的乘法

设[X]=xs.x1x2...xn,[Y]=ys.y1y2...yn原码一位乘法 X*Y 的规则如下:

  • 符号位 = xs ⊕ ys
  • 部分积 = X * yi
  • 部分积初值为 0。从 Y 的最低位 yn 开始,部分积 = 部分积 + yn * |X|,然后将部分积和 Y 逻辑右移一位。该步骤重复 n 次,进行加法运算也为 n 次

【例】x = -0.1101,y = 0.1011,进行原码一位乘法 x * y:

操作 通用寄存器(被乘数) ACC(高位部分积) MQ(低位部分积/乘数) MQ 丢失
初始状态,乘数 y=00.1011 00.1101 00.0000 1011
step1. 乘数最低位为 1,ACC 加 |X| 00.1101 00.1101 1011
step1. 部分积(和乘数)逻辑右移一位 00.1101 00.0110 1101 1
step2. 乘数最低位为 1,ACC 加 |X| 00.1101 01.0011 1101 1
step2. 部分积(和乘数)逻辑右移一位 00.1101 00.1001 1110 11
step3. 乘数最低位为 0,ACC 加 0 00.1101 00.1001 1110 11
step3. 部分积(和乘数)逻辑右移一位 00.1101 00.0100 1111 011
step4. 乘数最低位为 1,ACC 加 |X| 00.1101 01.0001 1111 011
step4. 部分积(和乘数)逻辑右移一位 00.1101 00.1000 1111 1011

符号位 = 1 ⊕ 0 = 1

x * y = -0.10001111

2.3.4 补码的乘法

设[X]=xs.x1x2...xn,[Y]=ys.y1y2...yn补码一位乘法 X*Y 的规则如下:

  • 部分积、被乘数采用双符号位补码;乘数采用单符号位补码
  • 符号位参与运算
  • Y 增设辅助位 yn+1 = 0
  • 部分积初值为 0。从 Y 的最低位 yn 开始:当 (ynyn+1) = (01)部分积 = 部分积 + [X];当 (ynyn+1) = (10)部分积 = 部分积 + [-X];其他情况加 0。然后将部分积和 Y 算术右移一位
  • 以上步骤重复 n+1 次,但最后一次不用移位。所以需要加法运算 n+1 次,移位 n 次

【例】x = -0.1101,y = 0.1011,进行补码一位乘法 x * y:

[x] = 11.0011,[-x] = 00.1101,[y] = 0.1011

操作 通用寄存器(被乘数) ACC(高位部分积) MQ(低位部分积/乘数) MQ(辅助位) MQ 丢失
初始状态,乘数 y=00.1011 11.0011 [负数: 00.1101] 00.0000 01011 0
step1. 乘数最低位和辅助位为 10,ACC 加 [-X] 11.0011 [负数: 00.1101] 00.1101 01011 0
step1. 部分积(和乘数)算术右移一位 11.0011 [负数: 00.1101] 00.0110 10101 1 0
step2. 乘数最低位和辅助位为 11,ACC 加 0 11.0011 [负数: 00.1101] 00.0110 10101 1 0
step2. 部分积(和乘数)算术右移一位 11.0011 [负数: 00.1101] 00.0011 01010 1 10
step3. 乘数最低位和辅助位为 01,ACC 加 [+X] 11.0011 [负数: 00.1101] 11.0110 01010 1 10
step3. 部分积(和乘数)算术右移一位 11.0011 [负数: 00.1101] 11.1011 00101 0 110
step4. 乘数最低位和辅助位为 10,ACC 加 [-X] 11.0011 [负数: 00.1101] 00.1000 00101 0 110
step4. 部分积(和乘数)算术右移一位 11.0011 [负数: 00.1101] 00.0100 00010 1 0110
step5. 乘数最低位和辅助位为 01,ACC 加 [+X] 11.0011 [负数: 00.1101] 11.0111 00010 1 0110

注:最后的 MQ = 00010 的最低位为原符号位,不用

[x * y] = 11.01110001,x * y = -0.10001111

2.3.5 原码的除法

设[X]=xs.x1x2...xn,[Y]=ys.y1y2...yn加减交替法(不恢复余数法)求 X/Y 的规则如下:

  • 首先,|被除数| - |除数| = 新余数
  • 若新余数为负:商 0,余数左移,然后加|除数|,得到新余数
  • 若新余数为正:商 1,余数左移,然后减|除数|,得到新余数
  • 以上两个步骤重复 n+1 次,最后一次若余数为负,商 0,需加上|除数|得到正确余数(余数为负,说明不够减,仅在此处恢复余数)
  • 总的加法运算为 n+1 或 n+2 次,移位总次数为 n 次

【例】x = 0.1011,y = 0.1101,利用加减交替法求 x / y:

|x| = 0.1011,|y| = 0.1101,[|y|] = 0.1101,[-|y|] = 1.0011

操作 通用寄存器(除数) MQ(被除数/部分余数) MQ(商)
初始状态:|x|=0.1011,|y|=0.1101 0.1101 [负数: 1.0011] 0.1011 0.0000
step0. |x|-|y| 0.1101 [负数: 1.0011] 1.1110 0.0000
step1. 部分余数为负,商 0 0.1101 [负数: 1.0011] 1.1110 0.0000
step1. 部分余数和商左移一位 0.1101 [负数: 1.0011] 1.1100 0.0000
step1. +|y| 0.1101 [负数: 1.0011] 0.1001 0.0000
step2. 部分余数为正,商 1 0.1101 [负数: 1.0011] 0.1001 0.0001
step2. 部分余数和商左移一位 0.1101 [负数: 1.0011] 1.0010 0.0010
step2. -|y| 0.1101 [负数: 1.0011] 0.0101 0.0010
step3. 部分余数为正,商 1 0.1101 [负数: 1.0011] 0.0101 0.0011
step3. 部分余数和商左移一位 0.1101 [负数: 1.0011] 0.1010 0.0110
step3. -|y| 0.1101 [负数: 1.0011] 1.1101 0.0110
step4. 部分余数为负,商 0 0.1101 [负数: 1.0011] 1.1101 0.0110
step4. 部分余数和商左移一位 0.1101 [负数: 1.0011] 1.1010 0.1100
step4. +|y| 0.1101 [负数: 1.0011] 0.0111 0.1100
step5. 部分余数为正,商 1 0.1101 [负数: 1.0011] 0.0111 0.1101
step6. 部分余数为正,不需要+|y| 0.1101 [负数: 1.0011] 0.0111 0.1101

x / y = +0.1101,余数 = 0.0111 * 2-4

2.3.6 补码的除法

设[X]=xs.x1x2...xn,[Y]=ys.y1y2...yn加减交替法求 X/Y 的规则如下:

  • 部分余数、被除数、除数采用双符号位补码
  • 符号位参与运算
  • 首先,若 X、Y 同号,则余数 = X - Y;若 X、Y 异号,则余数 = X + Y
  • 若余数与 Y 同号,则商 1,余数左移,减去 Y
  • 若余数与 Y 异号,则商 0,余数左移,加上 Y
  • 重复以上两个步骤 n 次,商末位恒置 1

【例】x = 0.1000,y = -0.1011,利用加减交替法求 x / y:

[x] = 00.1000,[x] = 00.1000

[y] = 11.1011,[y] = 11.0101,[-y] = 00.1011

操作 通用寄存器(除数) MQ(被除数/部分余数) MQ(商)
初始状态:x=00.1000,y=11.0101 11.0101 [负数: 00.1011] 00.1000 0.0000
step0. x、y 异号,+y 11.0101 [负数: 00.1011] 11.1101 0.0000
step1. 部分余数与 y 同号,商 1 11.0101 [负数: 00.1011] 11.1101 0.0001
step1. 部分余数和商左移一位 11.0101 [负数: 00.1011] 11.1010 0.0010
step1. 部分余数-y 11.0101 [负数: 00.1011] 00.0101 0.0010
step2. 部分余数与 y 异号,商 0 11.0101 [负数: 00.1011] 00.0101 0.0010
step2. 部分余数和商左移一位 11.0101 [负数: 00.1011] 00.1010 0.0100
step2. 部分余数+y 11.0101 [负数: 00.1011] 11.1111 0.0100
step3. 部分余数与 y 同号,商 1 11.0101 [负数: 00.1011] 11.1111 0.0101
step3. 部分余数和商左移一位 11.0101 [负数: 00.1011] 11.1110 0.1010
step3. 部分余数-y 11.0101 [负数: 00.1011] 00.1001 0.1010
step4. 部分余数与 y 异号,商 0 11.0101 [负数: 00.1011] 00.1001 0.1010
step4. 部分余数和商左移一位 11.0101 [负数: 00.1011] 01.0010 1.0100
step4. 部分余数+y(商末位恒置 1) 11.0101 [负数: 00.1011] 00.0111 1.0101

[x/y] = 1.0101,余数 = 0.0111 * 2-4

---EOF---

posted @ 2022-08-13 11:53  漫舞八月(Mount256)  阅读(376)  评论(0编辑  收藏  举报