数据的表示与运算

image

定点数

定点数,顾名思义,小数点的位置是固定的。存储整数时,默认小数点在数值部分后面;存储小数时,默认小数点在数值部分前面。也就是说定点数只能表示纯整数和纯小数

无符号数指所有的比特位都用于存储数值;有符号数指最高位用于表示符号,其他位用于存储数值。

最高位为0代表正数、1代表负数,其他位代表数值,为了便于观察,对于整数将符号位用","隔开,对于小数将符号位用"."隔开。注意:","和"."只是方便观察而已,完全可以去掉。这种表达方式被称作原码

\begin{array} {ll}x=+1110&[x]_{原}=0,1110\\
x=-1110&[x]_{原}=1,1110\\
x=+0.1101&[x]_{原}=0.1101\\
x=-0.1101&[x]_{原}=1.1101\\
\end{array}

但是用原码计算,CPU必须增加减法电路,加法用加法电路,减法用减法电路。如果都用加法来计算就会出错,例如,来计算一下1+(-1):

0000 0001
1000 0001
---------
1000 0010

结果为-2。结果明显是错的。

为了让减法可以用加法电路计算,我们用另外一种形式表示-1:

-1  = 0000 0000 - 0000 0001
    = 1111 1111

再来计算一下正数与负数的加法:

0000 0001
1111 1111
---------
0000 0000

结果为0,计算正确。这种表示负数的方式叫做补码。正数的补码与原码相同,负数的补码可以用0减去对应的正数计算

补码虽然解决了正数与负数的加法,但是补码无法直接用机器数比较大小,因为负数的最高位是1,机器数比正数大。

为了解决这个问题,我们不设符号位了,把所有的数都加一个偏置值,加完偏置值后所有的数都是正数,这样的话就没有正负数的问题了。这种编码方式叫做移码

移码=真值+偏置值

双符号位

补码、原码最高位代表符号。此时两个数相加减后,计算机需要判断是否溢出,这需要略微的复杂的电路作判断或增加一个进位寄存器。

还有一种方法,用两个符号位,可以直接从运算结果看出是非溢出。

00 正数
11 负数
01 上溢
10 下溢出

浮点数

定点数存在两个问题:1.只能存储纯整数或纯小数。2.表示的数据范围有限。

浮点数可以弥补定点数的不足,顾名思义浮点数的小数点可以浮动,将真值N写成科学计数法的形式:

N = S \times r^{j}

其中S为尾数,j为阶码,r是基数(通常为2)。若要存储N,只需用一个定点小数存储S,再用一个定点整数存储j即可。

为了提高浮点数的精度,其尾数的最高数位必须是一个有效值,否则需要调整尾数和阶码,这个过程称为规格化

IEEE 754标准规定浮点数格式如下:

image

因为浮点数必须规格化,尾数的最高数位必须是1,所以IEEE 754 标准中省略了这一位,称为隐藏位。

类型 数符 阶码 尾数数值 总位数 偏置值十六进制 偏置值十进制
短浮点数 1 8 23 32 7FH 127
长浮点数 1 11 52 64 3FFH 1023
临时浮点数 1 15 64 80 3FFFH 16383

例如将-8.25转换为浮点数,化为二进制为-1000.01,写成科学记数法-1.00001\times2^{11}

阶码用移码表示,所以加上偏移值:
11+01111111=10000010

尾数忽略小数点前面的1:
00001000000000000000000

所以-8.25的二进制为:

数符 阶码 尾数
1 10000010 00001000000000000000000

浮点数的加减法

浮点数的加减法分为三步:

  1. 对阶
  2. 尾数相加
  3. 规格化

为了直观,下面的例子并没有遵照IEEE 754 标准,而是阶码用十进制表示,尾数用原码表示,并且没有隐藏位:

\begin{array} {ll}100000000 + 5&\xlongequal{}0.1011111010111100001 \times 2^{27}+0.101 \times 2^{3}
\\&\xlongequal{对阶} 0.1011111010111100001 \times 2^{27}+0.00000000000000000000000101 \times 2^{27}\\&\xlongequal{舍入}0.1011111010111100001 \times 2^{27}+ 0.00000000000000000000001 \times 2^{27}\\&\xlongequal{尾数相加}0.101111101011110000100001\times 2^{27}\\ &\xlongequal{}100000008\end{array}

对阶按照小阶数化为大阶数的原则。

舍入是因为按照IEEE 754标准,浮点数尾数为23位。而0.000000000000000000000000101(小数点后有27位)不能用23位保存下来,所以舍入成0.00000000000000000000001(小数点后有23位),就是这里的舍入造成的误差。

定点数的移位运算

移位分为算术移位和逻辑移位。

算术移位符号位不参与移位。

码制 填补
整数 原码、补码、反码 0
负数 原码 0
补码 左移添0
右移添1
反码 1

定点数的溢出判断

方法一:采用一位符号位
设A的符号为A_s,B的符号为B_s,运算结果的符号为S_s,则溢出逻辑表达式为

V=A_sB_s\overline{S_s}+\overline{A_s}\overline{B_s}S_s

若V=0,表示无溢出;
若V=1,表示有溢出。
通俗来讲就是两个正数相加便成了负数或两个负数相加变成了正数。相加后只要保证符号位是正常的,就可以杜绝溢出。

方法二:采用一位符号位,根据数据位进位情况判断溢出

符号位进位C_s 最高数位的进位C_1
上溢 0 1
下溢 1 0

方法三:采用双符号位
正数符号为00,负数符号为11,运算后若两个符号位相同,没有溢出,不同则有溢出。

例如:

[A+C]_补= 00,0001111+00,1111100 = 01,0001011
[B-C]_补=11,1101000+11,0000100=10,1101100
[A+C]_补= 00,0001111+11,1101000 = 11,1110111
[B-C]_补=00,0001111+00,0011000=00,0100111

强制类型转换

强制类型转换的原则是尽量保证数值不变,所以范围小的数向范围大的数转换是没有误差的。但是从范围大的数向范围小的数转换就会出现误差。

int 强制转换成 short,由长变短直接将高位截断。

float 变 int,不知道怎么变,但肯定有误差。

数据的存储与排列

现代计算机都采用字节编址,即每个地址放一个字节数据。int、float等要存多个字节,这些字节的顺序可能不一样,例如01 23 45 67H

大端方式:01H 23H 45H 67H
小端方式:67H 45H 23H 01H

假设计算机数据线有32位,也就是一次可以读4字节,如果int存储地址是4的整数倍、short的存储地址是2的整数倍,那么一次指令就可以把数据取出,这种方式叫做“边界对其”。否则的话一个数据要取多次。

posted @ 2021-07-19 18:49:34
评论加载中...

发表评论