浮点数的表示和运算
浮点数表示法是指以适当的形式将比例因子表示在数据中,让小数点的位置根据需要而浮动。这样在位数有限的情况下,既扩大了数的表示范围,又保持数的有效精度。
浮点数的表示格式
浮点数由符号、尾数和阶码三部分组成,其表示的数值为:
式中,\(S\)取值0或1,用来决定浮点数的符号;\(M\)是一个二进制小输,称为尾数,一般用定点原码小数表示;\(E\)是一个二进制定点整数,称为阶码或指数,用移码表示。\(R\)是基数(隐含),可以约定为2、4、16等。
浮点数的表示范围与溢出
浮点数的表示范围是关于原点对称的:
数据一旦产生上溢,计算机必须中断运算操作,进行溢出处理。
数据下溢时,浮点数值趋于0,计算机将其当作机器零处理。
IEEE754标准
按照IEEE754标准,常用的浮点数格式有32位单精度浮点数(短浮点数,float型)和64位双精度浮点数(长浮点数,double型)。
类型 | 符号s | 阶码e | 尾数f | 总位数 | 偏置值 |
---|---|---|---|---|---|
单精度 | 1 | 8 | 23 | 32 | 7FH/127 |
双精度 | 1 | 11 | 52 | 64 | 3FFH/1023 |
float和double的基数都为2
隐藏位:对于规格化的二进制浮点数,尾数的最高位总是1,未来能使尾数多表示一位有效位,将这个1隐藏,称为隐藏位,因此23位尾数实际上表示了24位有效数字。IEEE754规定隐藏位1的位置在小数点之前。
偏置:在IEEE754标准中,指数用移码表示,但偏置不是通常n位移码所用的\(2^{n-1}\)而是\(2^{n-1}-1\).
规格化单精度浮点数的真值:
规格化双精度浮点数的真值:
IEEE754规定的特殊意义浮点数
定点、浮点表示的区别
对阶
尾数右移时,若舍弃有效位会产生误差,影响精度。为了保证运算的精度,尾数右移时,低位移出保留,并继续参加尾数部分的运算。
尾数加减
舍入
为保证运算精度,一般将移出的部位低位保留下来,参加中间过程的运算,最后再将运算结果进行舍入,还原成IEEE754格式。
IEEE754提供了四种可选的舍入模式:
溢出判断
若一个正整数超过了最大允许值(127/1023)则发生指数上溢,产生异常;
若一个负指数超过了最小允许值(-149/-1074),则发生指数下溢,通常按机器零处理。
尾数舍入(溢出):数值很大的尾数舍入时,可能因为末位加1而发生尾数溢出,此时需要通过右规调整尾数和阶码。
右规(上溢):右规时阶码加1,若加1后阶码全1,则发生指数上溢。(IEEE规定指数全1尾数非零为NAN)
左规(下溢):左规时阶码减1,阶码全0则发生指数下溢。
对于非规格化数的情况,尾数为0.0...01时,指数的最小允许范围是:-126-23=-129或-1022-52=-1074
不同类型数的混合运算时,遵循的原则是“类型提升”,即较低类型转换为较高类型。
转换时的精度、范围分析
int型转换为float型:不会发生溢出,但float尾数连隐藏位共24位,当int型的第24~31位非0时,无法精确转换成24位浮点数,需舍入处理,影响精度。
int型/float型转为double型:由于double型的有效位数更多,因此能保留精确值。
double型转为float型:float表示范围更小,因此大数转换时可能发生溢出;float尾数有效尾数更少,高精度数转换时发生舍入。
float型/double型转int型:由于int型没有小数部分,因此数据会向0方向截断(仅保留整数部分),因此发生舍入。int型表示范围更小,大数转换时可能会溢出。
在存储数据时,数据从低位到高位可以按从左到右排列,也可以按照从右到左排列。
通常用最低有效字节(LSB)和最高有效字节(MSB)来分别表示数据的低位和高位。
机器数 01 23 45 67H,其最高有效字节MSB=01H,最低有效自己LSB=67H
根据数据中各字节在连续字节序列中的排列顺序不同,可以采用两种排列方式:大端方式和小端方式。
大端方式:先存储高位字节,后存储低位字节。字中的字节顺序和原序列的相同。
小端方式:先存储低位字节,后存储高位字节。字中的字节顺序和原序列的相反。
边界对齐方式
数据按边界对齐方式存放要求其存储地址是自身大小的整数倍,半字地址一定是2的整数倍,字地址一定是4的整数倍。
当所存数据不满足上述要求时,可通过填充空白字节使其符合要求
字地址中的字指代4字节。
结构体对齐
在C语言中的struct类型中,“边界对齐”有两个重要要求:
struct A{
int a;
char b;
short c;
} // sizeof(A) = 8
struct B{
char b;
int a;
short c;
} // sizeof(B) = 12