吐槽:最近在学中国大学MOOC的一门课程《计算机系统基础(一)》,初学感觉对这些乱七八糟的码比较纠结,所以写个辨析,希望帮自己理清概念也希望帮到其他初学者。ps:纯属手敲和个人理解,不过有参考资料,如有错误希望大佬可以指出哈~
参考资料:MOOC、百度百科和其他人写的博客。
正文:
1、真值
真值可以理解为真正的值,一般用十进制表示,也可以用二进制表示。(其他进制表示的也有就是少而已)
举例:-85,100,-100,0
2、机器数
一个数在计算机中的二进制表示形式,而且是带符号的,0为正数,1为负数。
举例:10111,01111,011
在32位机器中,int、short、char型数据的机器数各占32位、16位、8位。
机器数与真值的关系:带符号位的机器数的真正数值为真值。
举例:机器数10111对应的真值为-7,也可为-0111B(二进制最好结尾写个B,不然不好区分,有时候会引起误会)
根据小数点的位置固定与否,机器数分为:定点数与浮点数。
小数点约定在固定位置的数称为定点数,小数点约定为可浮动的数称为浮点数。
因为X = (-1)^S * M * R^E
其中:S取值为0或1,用来约定X的符号;E为二进制定点整数,称为X的阶或指数;M为二进制定点小数,称为X的尾数;R为基数,一般为2、4、16等,2最常用。确定S、E、M三个数就可以确定浮点数X的值。
所以两者的关系是:浮点数可以由定点数得到。
以下介绍的由0/1序列表示的都是机器数的不同表示形式。
3、原码(从50年代开始,浮点数的小数用原码定点小数表示)
原码的表示:正数用0来表示,负数用1来表示,数值部分不变。
举例:0可表示为0000,-0为1000,-7为1111,5为0101(在此举例皆为4位原码)
缺点:0的表示不唯一,不利于编程;加减运算方式不统一,同号的数要比较绝对值才能做减法;额外的符号位不利于硬件设计。
用途:浮点数的小数用原码定点小数表示。
4、反码(不常用)
反码的表示:正数的原码是它本身;负数的原码是在其原码的基础上符号位不变,其余各位取反。
举例:+1的8位反码为00000001,-1的8位反码为11111110(-1的8位原码是10000001)
出现原因:反码的出现是为了解决原码做减法的问题。
缺点:无法解决0的表示不唯一的问题。
5、补码(从50年代开始,整数都用补码表示)
补码的定义:假设补码有n位,则[X]补 = 2^n + X(-2^n ≤ X<2^n,mod 2^n)(其中,X为真值,[X]补是机器数)
补码的表示:正数的补码就是它本身;负数的补码是在其反码的基础上+1得到的(即取反加一)。
举例:+1的8位补码为00000001,-1的8位补码为11111111(-1的8位反码是11111110)
相关结论:
1)一个负数的补码等于模减该负数的绝对值。
比如:-4的模12补码等于8
2)对于某一确定的模,某数减去小于模的另一数,总可以用该数加上另一数负数的补码来代替。
比如:9828 - 1928 = 9828 + (10^4 - 1928) = 9828 + 8072 = 17900 = 7900(mod 10^4)
3)一个负数的补码等于将对应正数补码各位取反、末位加1。
比如:-1000B的补码是00001000各位取反、末位加1即为11110111+1=111110000
求真值的补码:先将真值转换为二进制,正数取2^n的模,负数从右向左遇到第一个1的前面各位取反。
举例:设机器数有8位,123的补码表示为01111011,-123的补码表示为10000101
求补码的真值:符号位为0的正数,数值部分相同,符号位为1的负数,数值各位取反、末位加1。
举例:补码01010110的真值为86,补码11010110的真值为-42
出现原因:解决0的符号问题,统一表示;+和-的统一;能够多表示一个最低位(比如8位补码10000000可以表示-128)。
用途:整数用补码表示。运算器适合用补码表示和运算。
6、变形补码
变形补码(4‘s)的表示:双符号,用于存放可能溢出的中间结果。
举例:4位补码无法表示真值8,8的4位补码与-8的相同,均为1000,但变形补码不同,8的是01000,-8的是11000
用途:溢出的数可以同时保留符号位和最高数值位。
7、移码(用来表示浮点数的阶)
移码:将每一个数值加上一个偏置常数bias。
通常:当编码位数为n时,bias取2^(n-1)或2^(n-1)-1(当bias为 2^(n-1)-1 时,移码和补码仅第一位不同)
举例:E(biased) = E + 2^3(bias = 2^3 = 1000B)可以得到:-8(+8) ~ 0000B,0(+8) ~ 1000B
用途:移码用来表示浮点数的阶(便于浮点数加减运算时的对阶操作,比较大小)。
举例:1.01 * 2^(-1) + 1.11 * 2^3 中,运用移码可以简化比较:
将原式变为 1.01 * 2^(-1+4) + 1.11 * 2^(3+4) 就可以得到011(3)<111(7)
推荐阅读:(这些会帮助了解这些编码的来源与发展)
http://legendmohe.net/2013/08/22/补码、负数和减法/
https://www.zhihu.com/question/20159860/answer/71256667
补充:
18/12/27:有人给我推荐《计算机科学导论》,我看到了这个书里面关于这些码的详述,觉得非常清楚。