我是靠谱客的博主 无心小丸子,最近开发中收集的这篇文章主要介绍【考研计组】有符号数与无符号数之间的转换,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

楼主有话要说:

在复习《计算机组成原理》时,遇到了有符号数与无符号数之间转换的问题,为了应对这类问题,楼主仔细查阅资料再结合做题总结出一些心得,内容如下(如果有新的总结,会反复修改):

注意:

1、字长都用的是 16 位(方便些)

2、建议先去大致了解下 C++ 里基本数据类型的字节长度和示数范围;如:

char1 byteint

4 byte 

short [int]2 bytefloat4 bytelong [int]4 byte
signed char1 bytesigned int4 bytesigned short [int]2 bytedouble8 bytesigned long [int]4 byte
unsigned char1 byteunsigned int4 byteunsigned short [int]2 bytelong double8 byteunsigned long [int]4 byte

3、(1)定点整数的范围( 16 bit ) :有符号:-32767 <= x <= 32767

(2)定点整数补码的范围( 16 bit ) :有符号:-32768 <= x <= 32767

4、在计算机中,负数一般用补码表示。注意:本文所有例子,都是先将要赋值的数化为补码的形式再进行转换。

5、理清 0 和 1 的原码、反码、补码。(0 的补码和移码是只有一种形式;正数的原码、反码、补码都相同;)

原码反码补码
[ +0 ]0000 00000000 00000000 0000
[ -0 ]1000 00001111 11110000 0000
[ +1 ]0000 00010000 00010000 0001
[ -1 ]1000 00011111 11101111 1111

一、同类型(如同为有符号数,或同为无符号数)转换

(一)1. 同为无符号数(由短变长:在最高位加 “ 0 ”。)

unsigned short x = 255;  //short为2字节

unsigned int y = x;  //int为4字节

x = 255 D = 1111 1111 B

y = 0000 0000 1111 1111 B = 255 D

总结:同为无符号数时,由较短的数变成较长的数,即在最高位加 “ 0 ”,称为 “ 零扩展 ”。

(一)2. 同为无符号数(由长变短:在最高位加 “ 0 ”。)

unsigned int x = 255;  //short为2字节

unsigned short y = x;  //int为4字节

x = 255 D = 0000 0000 1111 1111 B

y = 1111 1111 B = 255 D

总结:同为无符号数时,由较长的数变成较短的数,即去掉高位的 “ 0 ” 字节,低位的字节不变。

(二)同为有符号数(由短变长和由长变短的情况同 “(一)同为无符号数 ” 一样)

short x = -120;  //short为2字节

int y = x;  //int为4字节

x = -120 D ,其原码为:1111 1000 B,其补码为:1000 1000 B (= 88 H)

y = 1111 1111 1000 1000 B = -120 D (= FF 88 H)

总结:同为有符号数时,使用符号扩展,即为负数时,高位的字节加 “ 1 ”;为正数时,高位的字节加 “ 0 ”。

二、有符号数与无符号数之间的转换

(一)有符号数转为无符号数

short n = -1;

unsigned short m = n;

n = -1 D,其补码为:1111 1111 B 

m = 1111 1111 B = 65535 D

注释:n 的最高位为 “ 1 ” 表示的是符号位,因为 m 为无符号数,所以 m 的最高位为 “ 1 ” 表示的是“ 2的7次方 ”。

总结:有符号数转为无符号数时,当有符号数为负数时,关键是将最高位的 “ 1 ” 变成 “ 2的某次方 ”。

(二)无符号数转为有符号数

unsigned short a = 65535;

short b = -1;

a = 65535 = FF FF FF FF H

b 的补码即为:FF FF FF FF H = -1 D

注释:因为 b 为有符号数,最高位可知为 “ 1 ”,所以 b 为负数,可知其值为 -1。

总结:无符号数转为有符号数时,先得出赋值数的补码,即为被赋值数的补码;再由被赋值数的补码取反加一得到原码,再计算即得十进制的数值。

再举个例子:

unsigned char i = 130;

char k = i;

i = 130 D = 1000 0010 B (注意:正数的原码 = 正数的补码 = 正数的反码)

k 的补码为:1000 0010 B,进行取反加一后得原码为:1111 1110 B,因为 k 为有符号数,最高位又为 “ 1 ”,所以 k 为负数,即为 -126 D。

练习:(附上2011年统考真题,便于理解巩固)

假定在一个8位字长的计算机中运行如下C程序段:

unsigned int x = 134;
unsigned int y = 246;
int m = x;
int n = y;
unsigned int z1 = x - y;
unsigned int z2 = x + y;
int k1 = m - n;
int k2 = m + n;

若编译器编译时将 8 个 8 位寄存器 R1 - R8 分别分配给变量x、y、m、n、z1、z2、k1、k2,请回答下列问题(提示:带符号整数用补码表示)

( 1 )执行上述程序段后,寄存器 R1、 R5 和 R6 的内容分别是什么?(用十六进制表示)

( 2 )执行上述程序段后,变量 m 和 k1 的值分别是多少?(用十进制表示)

( 3 )上述程序段涉及带符号整数加/减、无符号整数加/减运算,这四种运算能否利用同一个加法器辅助电路实现?简述理由。

( 4 )计算机内部如何判断带符号整数加/减运算的结果是否发生溢出?上述程序段中,哪些带符号整数运算语句的执行结果会发生溢出?

解:( 1 )寄存器 R1、 R5 和 R6 的内容,分别对应 x, z1(x - y) , z2(x + y)。

x = 134 D,其原码等于补码为 1000 0110 B,即为 86 H,即为 R1

y = 246 D,其原码等于补码为 1111 0110 B,即为 F6 H

z1 = x - y = x 的补码 + [-y] 的补码 = 1000 0110 B + 0000 1010 B = 1001 0000 B = 90 H,即为 R5

z2 = x + y = x 的补码 + y 的补码 = 1000 0110 B + 1111 0110 B = (1) 0111 1100 B = 7C H,即为 R6

(注意:z2 处有溢出,但无符号整数的加减运算,一般不考虑溢出情况,只是输出的时候若是有符号数的最高位是符号位,意思是 z2 若转换为有符号数,最高位为 1。)

所以 R1 = 134 = 86 H;
        R5 = 90 H;
        R6 = 7C H;

( 2 )m 为无符号数整型 x 转为有符号数整型,n 为无符号数整型 y 转为有符号数整型,由(1)知

x 的补码为 1000 0110 B,y 的补码为 1111 0110 B,所以

m 的补码为 1000 0110 B,其原码为1111 1010 B,其值为 -122 D

n 的补码为 1111 0110 B,其原码为 1000 1010 B,其值为 -10 D

即 k1 = m - n = m 的补码 + -n 的补码 = 1000 0110 B + 0000 1010 B = 1001 0000 B = 90 H,求得其原码为 1111 0000 B = -112 D

顺带求下 k2 = m + n = m 的补码 + n 的补码 = 1000 0110 B + 1111 0110 B = (1) 0111 1100 B = 7C H(注意:此处有溢出)

所以,m = -122;
           k1 = -112;

题外话(对 OF 、SF、CF 也要注意区分):

k2 = m + n,由已知 m = -122,n = -10,可知两者相加仍为负数,但结果为正。所以,溢出标志位 OF = 1, 表示溢出,说明寄存器 R6 中的内容不是真正的结果;符号标志位 SF = 0,表示结果为正数(溢出标志为1,说明符号标志有错),进位标志位 CF = 1,仅表示加法器最高有进位,对运算结果不说明什么。

( 3 ) 能。n 位加法器实现的是模 2 的 n 次方无符号整数加法运算。因为在计算机中,正数和负数均用补码来表示,带符号整数的加法运算和无符号整数的加法运算,均可直接用加法器实现。对于减法运算,只要减数的补码加上被减数的负数的补码即可实现,但要考虑溢出情况。所以带符号整数加/减、无符号整数加/减运算均可用同一个加法器辅助电路实现(溢出判断电路不同)。

( 4 )是。计算机内部判断带符号整数加/减运算的结果是否发生溢出,有 3 种方法。一是若加法器的两个输入端(加法)的符号相同,且不同于输出端(和)的符号,则结果溢出。二是加法器完成加法操作时,若次高位(最高数位)的进位与最高位(符号位)的进位不同,则结果溢出。三是两个带符号整数均为负数,两者相加后,结果小于 8 位二进制所能表示的最小负数,则结果溢出。

在执行关于 k2 的语句时会发生溢出。k2 = 1000 0110 B + 1111 0110 B = (1) 0111 1100 B,括号中为加法器的进位,因为 2 个带符号整数均为负数,经过加法运算后得出结果的最高位为 0 ,所以溢出。

(溢出判断方法简单版:双符号位判决法、最高位进位、符号相同操作数的运算后与原操作数的符号不同,则结果溢出。)

注释:

双符号位判决法:

用补码进行双符号位运算(正数符为 00, 负数符号为 11),第一符号位表示最终结果的符号,第二符号位表示运算结果是否溢出。第一符号位和第二符号位相同,则未溢出,;若不同,则溢出。具体如下:

若运算结果的符号位为 01, 则为正溢出;

若结果双符号为 10, 则为负溢出;

若结果的双符号位为 00,结果为正数,无溢出。

若结果的双符号位为 11,结果为负数,无溢出。

最后

以上就是无心小丸子为你收集整理的【考研计组】有符号数与无符号数之间的转换的全部内容,希望文章能够帮你解决【考研计组】有符号数与无符号数之间的转换所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部