计算机数据表示

1、进制

1.1 进制的由来

进制:是一种进位的方式。x进制,表示逢x进1。 

计算机的电子原件的状态:开,关。 

那么,我们表达数据的时候,也是按照开,关的状态来表示的。

如果我们表达数据仅仅使用这两种昨天,那么能够表达的数据是比较少的。 

而我们常见的数据,英文字母,数字,标点符号,这就很多了。 

为了能够表示更多的数据,国际化组织就规定,用8个这样的信号来表示一个数据,并且用1,0表示两种状态,这个数据的单位叫:字节。 

由这样的1,0组成的数据就是二进制数据。 

- 单位转换 

1byte=8bit 

1kB=1024byte 

1MB=1024kB 

1GB=1024MB 

1T=1024GB 

- 基础补充: 

大写B(byte),字节;小写b(bit),比特; 

1B=8b,即一个字节等于8个比特位。 

1KB=8kb,k表示千,即1千字节等于8千比特。一般来说,计算机中的进位是1024进位的,但是在通信中,为了方便计算,通常用千进位。 

(为什么要用1024进位,因为计算机码是以二进制为基础,2的幂数可以反映二进制的位数,因为2的10次幂是1024,最接近1000(1K),方便十进制的估算。) 

1byte=8bits,两者换算是1:8的关系。

1Byte就是1个字节,1个字节是由8个二进制位组成。

1.2 进制的表示

定义: 

二进制数 

每一位使用两个不同数字表示(0,1

低位和高位的关系是:逢2进1

各位的权值是2的整数次幂(基数是2)

标志:尾部加B

例:101.01B=1×22+0×22+1×20,+0×2−1+1×2−2=5.25

八进制数 

每一位使用八个不同数字表示(0,1,2,3,4,5,6,7

低位和高位的关系是:逢8进1

各位的权值是8的整数次幂(基数是8)

标志:尾部加Q

例:365.2Q=3×82+6×81+5×80+2×8−1=245.25

十六进制 

每一位使用十六个不同数字表示(0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

低位和高位的关系是:逢16进1

各位的权值是16的整数次幂(基数是16)

标志:尾部加H

例:F5.4H=15×161+5×160+4×16−1=245.25

第一种表示方式: 

(1100101100)2=(1454)8

(1100101100)2=(32C)16

第二种表示方式(在末尾加字母): 

例如:二进制再末尾加B,十进制加D,八进制加Q,十六进制加H

1.3 进制的转换

1.3.1 R进制转十进制使用按权展开法

其具体操作方式为:将R进制数的每一位数值用RKRK形式表示,即幂的底数是R,指数为K,K与该位和小数点之间的距离有关。当该位位于小数点左边,K值是该位和小数点之间数码的个数,而当该位位于小数点右边,K值是负值,其绝对值是该位和小数点之间数码的个数加1。

例如 二进制: 10100.01=1⋅24+1⋅22+1⋅2−2=20.2510100.01=1·24+1·22+1·2−2=20.25 

例如 七进制 604.01=6⋅72+4⋅70+1⋅7−2≈298.02604.01=6·72+4·70+1·7−2≈298.02

1.3.2 十进制转R进制

如果是整数,直接使用短除法。(例如将94转换为二进制。)

得到结果为1011110 

- 如果是浮点数,对整数和小数分开转换;整数部分:除以2取余,小数部分:乘以2取整。(例如29.6875 -> 11101.1011B)

注意十进制小数(如0.63)在转换时会出现二进制无穷小数,这时只能取近似值。

1.3.3 二进制与八进制的互换(用三位二进制数一组表示一位)与十六进制数(用四位二进制数一组表示一位)

- 八进制 -> 二进制:把每个八进制数字改写成等值的3位二进制数,且保持高地位的次序不变。 

例:2 4 6 3 2 Q - > 

010 100 110 111 011 010 B 

- 二进制 ->八进制:整数部分从低位到高位每3组用一个等值的八进制数来替换,不足3位时在高位补0凑满3位;小数部分从高位向低位每3位用一个等值八进制数来替换,不足3位时在低位补0凑满三位。 

例:1 101 001 110. 110 01B -> 

001 101 001 110. 110 010B -> 

1 5 1 6 6 2Q

3. 机器数采用原码,反码和补码等编码方法,称为码制。

3.1 机器数与真值

3.1 机器数 

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。 

那么,这里的 00000011 和 10000011 就是机器数。

3.2 真值 

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。 

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

3.2 原码,反码和补码

3.2.1 概念

在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式. 

- 原码 

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制: 

[+1]原 = 0000 0001 

[-1]原 = 1000 0001 

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是: 

[1111 1111 , 0111 1111] 即 [-127 , 127] 

原码是人脑最容易理解和计算的表示方式. 

- 反码 

反码的表示方法是:正数的反码是其本身 

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反. 

[+1] = [00000001]原 = [00000001]反 

[-1] = [10000001]原 = [11111110]反 

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算. 

- 补码 

补码的表示方法是: 

正数的补码就是其本身 

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) 

[+1] = [00000001]原 = [00000001]反 = [00000001]补 

[-1] = [10000001]原 = [11111110]反 = [11111111]补 

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

3.2.2. 为何要使用原码, 反码和补码

现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:

[+1] = [00000001]原 = [00000001]反 = [00000001]补

1

所以不需要过多解释. 但是对于负数:

[-1] = [10000001]原 = [11111110]反 = [11111111]补

1

可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别”符号位”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了. 

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码: 

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

1

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数. 

为了解决原码做减法的问题, 出现了反码: 

计算十进制的表达式: 1-1=0 

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0 

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在”0”这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0. 

于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

1

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128: 

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补 

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

3.2.3 总结:

原码是最符合人脑的,用最高位表示符号位,其余位表示数值位。

反码是为了方便带符号的机器数之间运算,让符号位也参与运算。(原理是对原码操作,符号位不变,数值位取反)(注意结合1-1这个例子来理解!)

补码是为了解决-0以及[00000000]原和[10000000]原两个编码都表示0这个问题,在反码的基础上加1,就能只用[00000000]来表示0了,[10000000]则表示-128.(原理是对反码基础上加1)(注意结合1-1和-1-127这两个例子来理解!)


转自:

https://blog.csdn.net/sgq_csdn/article/details/79181440#11-进制的由来,个人感觉这篇文章写得非常赞,强烈推荐

你可能感兴趣的:(计算机数据表示)