计算机中数的表⽰和存储(总结)
⼀、⽆符号数和有符号数
1.⽆符号数
计算机中的数均存放在寄存器中,通常称寄存器的位数为机器字长。所谓的⽆符号数即没有符号的数,在寄存器中的每⼀位均可⽤来存放数值。⽽当存放有符号位时,则留出位置存放“符号”。因此,在机器字长相同时,⽆符号数与有符号数所对应的数值范围是不同的。以机器字长16位为例⼦,⽆符号数的范围为0~(216-1=65535),⽽有符号数的表⽰范围为(-32768=215)~(+32767=215-1)(此数值对应原码表⽰)。机器中的有符号数是⽤补码表⽰的。
2.有符号数
对于有符号数⽽⾔,符号的正负机器是⽆法识别的,⽽在机器中是⽤0,1分别表⽰正,负的,并规定将它放在有效数字的前⾯,这样就组成了有符号数。
把符号“数字化”的数叫做机器数,⽽把带“+”或“-”符号的数叫做真值。⼀旦符号数字化后,符号和真值就形成了⼀种新的编码。有符号数有原码、补码、反码和移码等四种表⽰形式。
2.1 有符号数的编码⽅法-原码表⽰法
原码是机器数中最简单的⼀种表⽰形式,其符号位为0表⽰正数,为1表⽰负数,数值位即真值的绝对值,故原码⼜称作带符号位的绝对值表⽰。
整数原码的定义为
式中x为真值,n为整数的位数。例如,当x=-1110时,[x]原=24-(-1110)=11110
⼩数的原码定义为
例如,当x=-0.1101时,[x]原=1-(-0.1101)=1.1101
当x=0时
[+0.0000]原=0.0000
[-0.0000]原=1-(0.0000)=1.0000
可见[+0]原不等于[-0]原,即原码中的零有两种表⽰形式。
原码编码的优缺点
其表⽰简单明了,易于和真值转换,但⽤原码进⾏加减运算时,确带来了许多⿇烦。
2.2 有符号数的编码⽅法-补码表⽰法
补码利⽤了⽣活中的“补数”的概念,即以某个数为基准,称为模数,该数对模数的取模运算的结果就是补数。例如,-
3=+9(mod12),4=4(mod12)=16(mod12)。
所以,⼀个负数可⽤它的正补数来代替,⽽这个正补数可以⽤模加上负数本⾝求得。这样减法可以⽤加法替代。
整数补码的定义为
式中x为真值,n为整数的位数。例如,当x=-1110时,[x]原=24+1+(-1110)=10010
⼩数补码的定义为
例如,当x=-0.1101时,[x]原=2+(-0.1101)=10.0000-0.1101=1.0011
当x=0时
[+0.0000]补=0.0000
[-0.0000]补=2+(-0.0000)=10.0000-0.0000=0.0000
或  [+0]补=00
[-0]补=21+1+(-0)=100-0=00
可见[+0]原=[-0]原,即原码中的零只有⼀种表⽰形式。
对于x=-1,若将其看成整数,则[-1]补=21+1 +(-1)=100-1=11;若将其看成⼩数,有[-1]补=2+(-1)=10.0000-1.0000=1.0000。可见,-1本不属于⼩数范围,但却有[-1]补存在,故它能⽐原码多能表⽰⼀个“1”。
原码和补码的转换准则:
对于负数(整数或⼩数),⽆论是原码→补码还是补码→原码,都遵守“除符号位外,每位取反,末位加1”得到,⽽原码→补码遵守“符号位不变,每位取反”。
2.3 有符号数的编码⽅法-反码表⽰法
反码通常⽤来作为由原码求补码或者由补码求原码的中间过渡。反码的定义如下:
整数补码的定义为
式中x为真值,n为整数的位数。例如,当x=-1110时,[x]原=(24+1-1)+(-1110)=10001
⼩数反码的定义为
例如,当x=-0.1101时,[x]原=(2-2-4)+(-0.1101)=1.1111-0.1101=1.0010
当x=0时
[+0.0000]补=0.0000
[-0.0000]补=(10.0000-0.0001)+(-0.0000) = 1.1111
可见[+0]原不等于[-0]原,即原码中的零有两种表⽰形式。
有[y]补→[-y]补,⽆论真值是正还是负,都是采⽤“连同符号位在内,每位取反,末位加1”的规则。
2.4 三种编码⽅式+
对于机器字长为n(例如8),⽆符号数的范围为0~(2n-1)=255,原码、反码的范围为-(2n-1-1)=-127~(2n-1-1)=127,补码范围为-(2n-1)=-128~ (2n-1-1)=127。考虑⼀个机器码10000000=0x80,对应⽆符号数就为128;原码为-0;反码为-127(对应原码为11111111);补码为-
128(由于补码可以表⽰最⼩的负数-2n=7=-128(真值)即[-128]补=27+1-1000000=10000000或=28+1-
1000000=1 10000000,即看成如果是9位则变成原码为1 10000000,但只有8位所以10000000补码就表⽰-128,⽽这个数字在原码和反码中都没法表⽰)。
2.5 移码
当真值⽤补码表⽰时,由于符号位和数值部分⼀起编码,与习惯上的表⽰法不同,因此⼈们很难从补码的形式上直接判断其真值的⼤⼩。
如果我们对每个真值加上⼀个2n(n为整数的位数),则可以直接⽐较各数的⼤⼩了。
由此可得移码的定义为
[x]移=2n+x  (2n>x≥-2n)
式中x为真值,n为整数的位数。从其定义可以看出:移码的⾸位⼀样表⽰符号位,但和上述三种编码不同,其0表⽰为负数,1表⽰为整数。其实移码就是在真值上加上⼀个常数2n。在数轴上移码所表⽰的范围恰好对应于真值在数轴上的范围向轴的正⽅向移动2n个单元。由此得移
码之称,如下图所⽰:
当x=0时
[+0]移=25+0=1,00000
[-0]移=25-0=1,00000
可见,[+0]移=[-0]移,即移码表⽰中零也是唯⼀的。printf直接输出数字
由移码的定义知,当n=5时,其最⼩的真值为x=-25=-100000,则[-100000]移=25+x=0,00000,即最⼩真值的移码为全0。利⽤移码这⼀特点,当浮点数的阶码⽤移码表⽰时,就能⽅便地判断阶码的⼤⼩。
进⼀步观察可以发现,同⼀个真值的移码和补码仅差⼀个符号位。
⼆、 C/C++语⾔中如何处理
C/C++语⾔中有unsigned类型、int类型及long int类型对应于整型的表⽰,计算机存储有符号数都是⽤补码表⽰的(实验验证)。win32下的位数分别都为4Bytes,则⽆符号表⽰的范围为0~232-1=4294967295,int表⽰的范围为-231~231-1(补码确定的)。
对于1个int类型的数据,当给其赋值时(即我们给的真值),当计算机对其进⾏存储时,都将该真值编码成了补码的形式,⽽当以%d形式(带符号的整型)输出时⼜转变成我们的真值,以x%形式(⼗六进制⽆符号整数)输出时则直接输出为补码形式的机器码)。例如:
int a = -8;
printf("%d,%x\n",a,a);
则输出的结果为-8,fffffff8。
当输⼊的数越界时(⽐如说给int赋值超过231-1=2147483647或者-231),则同样将该该数转变成补码形式,然后截断超过的位数。例如:int a = 2147483649;
printf("%d,%x\n",a,a);
将a表⽰成机器码为ff ff ff ff + 2 = 80 00 00 01(最⾼位进位直接去掉),⽽该补码形式对应的原码为ff ff ff ff,故对应输出的真值为-(231-1);当输⼊为231=2147483648时,输出为-231,当超过负数的界时,输出⼀直未-231。
另外,⽆符号整数unsigned int中最⾼位不表⽰符号位,故当给⽆符号整数类型的变量赋值⼀个负数时,计算机存储时将其存为对应的补码形式,⽽输出的时候则不将⾸位1看成符号位。例如:
unsigned m5 = -8;
printf("%d,%u,%x,%d\n",m5,m5,m5);
则输出为-8,4294967288,fffffff8.同样,对⽆符号的输出超过上界时,其输出⼀直为232-1.
C/C++中的各种数据类型可以进⾏转换,以其输出格式定。记住⼀点,有符号数在计算机中存储的都是补码形式。⽽当为⽆符号数时,在计算机中存储的形式即可以看成⽆符号数也可以看成有符号数(此时该机器码为有符号数的补码),故其输出的结果由输出的格式决定。当他们以⼗六进制或⼋进制输出时,输出的都是机器码,故不管是有符号还是⽆符号数,当他们的机器码⼀样时,输出的结果都⼀样。
参考⽂献:唐朔飞,计算机组成原理

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。