二进制小数: 点左边的位的权是2的正幂,点右边的位的权是2的负幂。刚好小于1的数,如0.111111将用简单的表达法1.0-ε来表示这样的数值。
IEEE浮点数:定点表示法不能很有效地表示非常大的数字
- 符号S决定这个数是负数(S=l)还是正数(S=0),对于数值0的符号位解释作为特殊情况处理。
- 尾数(significand) M是一个二进制小数,它的范围是1 ~ 2-ε,或者是0〜1-ε
- 阶码E 的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)。
特殊浮点数:
当exp的位模式既不全为0 (数值0),也不全为1 (单精度数值为255,双精度数值为2047)时,阶码字段被解释为以偏置形式表示的有符号整数。阶码的值是E = e-Bias,其中e是无符号数,而Bias是一个等于 (单精度是127,双精度是1023)的偏置值。指数的取值范围,对于单精度是-126~ +127,而对于双精度是-1022 ~ +1023。
对小数字段frac的解释为描述小数值f,其中0≤f<1,其二进制小数点在最高有效位的左边。尾数定义为M=1+f。有时,这种方式也叫做隐含的以1开头。
当阶码域为全0时,所表示的数就是非规格化形式,而尾数的值是也就是小数字段的值,不包含隐含的开头的1。
作用:
1、提供了一种表示数值0的方法,+0.0的浮点表示的位模式为全0,根据IEEE的浮点格式,认 为值+0.0和-0.0在某些方面是不同的,而在其他方面是相同的。
2、表示那些非常接近于0.0的数。称为渐溢出,数值分布均匀地接近于0.0。
当指阶码全为1的时候出现的。当小数域全为0时,得到的值表示无穷,无穷能够表示溢出的结果。
当小数域为非零时,结果值被称为“NaN”,就是“不是一个数"(Not a Number)的缩写,在某些应用中,表示未初始化的数据时,它们也很有用处。
舍入:表示方法限制了浮点数的范围和精度,浮点运算只能近似地表示实数运算。因此,对于 值x,我们一般想用一种系统的方法,能够找到“最接近的”匹配值x。
IEEE浮点格式定义了四种不同的舍入方式。默认的方 法是找到最接近的匹配,而其他三种可用于计算上界和下界。
向偶数舍入在大多数现实情况中避免统计偏差。在50%的时间里,它将向上舍入,而在 50%的时间里,它将向下舍入。不想舍入到整数时,也可以使用向偶数舍入,我们只是简单地考虑最低有效数字是奇数还是偶数。向偶数舍入法能够运用于二进制小数,我们将最低有效位的值0认为是偶数。
浮点运算:IEEE标准中指定浮点运算行为方法的一个优势在于,它可以独立于任何具体的硬件或者软件实现。当参数中有一个是特殊值(如-0、或NaN等)时,IEEE标准定义了一些使之更合理的规则。例如,定义 1/-0将产生-∞,而定义1/+0会产生+∞。
表达式(3.14+lel0)-lel0求值得到0.
表达式3.14+(lel0-lel0)得到值3.14
+ ∞ -∞=NaN
NaN+x = NaN
浮点加法不具有结合性
例如,假设一个编译器给定了如下代码片段:
x = a + b + c; .
y = b + c + d;
编译器可能试图产生下列代码来省去一个浮点加法:
t = b + c;
x = a + t;
y = t + d;
对于x来说,这个计算可能会产生与原始值不同的值,因为它使用了加法运算的不同的结合方式。在大多数应用中,这种差异小得无关紧要。编译器倾向于保守,避免任何对功能产生影响的优化,即使是很轻微的影响。
另一方面,浮点加法满足了单调性属性:如果a≥b,那么对于任何a、b以及x的值,除了NaN,都有x+a≥x+ b。无符号或补码加法不具有这个实数(和整数)加法的属性。
对于任何a、b和c,并且a、b和c都不等于NaN,浮点乘法满足下列单调性:
C语言中的浮点数:所有的C语言版本提供了两种不同的浮点数据类型:float和double。在支持IEEE浮点格式的机器上,这些数据类型就对应于单精度和双精度浮点,使用向偶数舍入的方式。较新版本的c语言,包括ISO C99,包含第三种浮点数据类型long doubleo对于许多机 器和编译器来说,这种数据类型等价于double数据类型。不过对于Intel兼容机来说,GCC用 80位“扩展精度”格式来实现这种数据类型,提供了比标准64位格式大得多的取值范围和精 度。
C语言标准不要求机器使用IEEE浮点,所以没有标准的方法来改变舍入 方式或者得到诸如-0、+ ∞、或者NaN之类的特殊值。
大多数系统提供include (・h,) 文件和读取这些特征的过程库,但是细节因为系统不同而不同。
类型转换:
- 从int转换成float,数字不会溢出,但是可能被舍入。
- 从int或float转换成double,因为double有更大的范围(也就是可表示值的范围), 也有更高的精度(也就是有效位数),所以能够保留精确的数值。
- 从double转换成float,因为范围要小一些,所以值可能溢出成为+ ∞或-∞。另外, 由于精确度较小,它还可能被舍入。与Intel兼容的微处理器指定位模式[10...00](字长为w时的TMin为 整数不确定值。一个从浮点数到整数的转换,如果不能为该浮点数找到一个合理的整数近似值,就会产生这样一个值。因此,表达式(int)+le10会得 到—21483648,即从一个正值变成了一个负值。
IA32-FP : Intel IA32的浮点运算
IA32处理器有特别的存储器元素,称为寄存器,当计算或者使用浮点数时,用来保存浮点值。IA32非同一般的属性是,浮点寄存器使用一种特殊的80位的扩展精度格式,提供了更大的表示范围和更高的精度。所有单精度和双精度数在从存储器加载到浮点寄存器中时,都会转换成这种格式。当数字存储在存储器 中时,它们就从扩展精度转换成单精度或者双精度格式。
对于程序员而言,把所有寄存器数据扩展成80位,并把所有存储器数据收缩成更小的格式的做法,会产生一些不太好的结果。这意味着从寄存器存储一个值到存储器中,然后再把它取回到寄存器中,由于舍入、下溢或者上溢,可能会改变它的值。对于C语言程序员来说,这种存入和取出并不总是可见的,因而会导致一些异常的结果。
较新版本的Intel处理器,包括IA32和较新的64位机器,对单精度和双精度浮点运算提供了直接的硬件支持。随着硬件以及基于较新的浮点指令产生代码的新编译器的使用,以前 IA32做法导致的这些奇怪特性会逐渐消失。
练习:
答案:
小数值 |
二进制表示 |
十进制表示 |
1/8 |
0.001 |
0.125 |
3/4 |
0.11 |
0.75 |
25/16 |
1.1001 |
1.5625 |
43/16 |
10.1011 |
2.6875 |
9/8 |
1.001 |