标题:浮点类型深谈1.编写本文目的浮点运算已属常用,但仍有深究必要,以消除其中可能的错误使用。2.预期读者3.编者语㈠ 在其他任何公共论坛上转载本文,请标明出处和作者,而无需授权和确认。4.正文㈠ float格式简谈Inter 80386/80387 及以上型号CPU有三种浮点类型,即短实数、长实数和80位临时实数,分别占用4字节、8字节和10字节,对应着C/C++中的float、double和long double[注1],我以 Real4、Real8和Real0表示之。每种浮点格式皆应符合IEEE标准,称为规格化数,不符合IEEE标准的浮点格式称为非格式化数(NAN),我以最简单的float格式举例。Float格式数据长32 bits,最高位为符号位:0为正,1为负;紧接着的8位为阶码:为了便于比较大小,其固定偏移7FH长,即0实际表示-7FH,7FH实际表示0,0FFH实际表示80H;余下的低23位为尾数(有效数字),为了使有效数字达到最大精度,这23个有效数字隐含着固定位1[注2],比如尾数10000000000000000000001其实就是1.10000000000000000000001,1被省略,而小数点固定在首位。根据以上规则可以知道float所能表示的绝对值大小范围是0 000,0000,0 000,0000,0000,0000,0000,0000 B 至 0 111,1111,1 111,1111,1111,1111,1111,1111 B即±1.00000000000000000000000B×2(0x00-0x7F) 到±1.11111111111111111111111B×2(0xFF-0x7F)然而事实上并不是这样,因为从这个范围可以看出它并不能表示0.0,而0.0为常用数字,所以特别规定±1.00000000000000000000000B×200为零,规定指数为0xFF的数字为非法数字,因此float实际的绝对值范围(除去0以外)是0 000,0000,0 000,0000,0000,0000,0000,0001 B 至 0 111,1111,0 111,1111,1111,1111,1111,1111 B即 0 并上 ±1.00000000000000000000001B×2(0x00-0x7F) 到±1.11111111111111111111111B×2(0xFE-0x7F)可能的格式状态:+不支持+非有效数-不支持-非有效数+规格化+∞-规格化-∞+0+空-0-空+不能规格化-不能规格化可能的异常:无效操作上溢下溢除零不可规格化操作数精度不足㈡ 注意事项a. 可以看出0可以用+0表示,也可以用-0表示,为此,CPU在比较零值时作了特殊处理,结果是±0虽然在存储器上格式不同,但比较值相同,然而如果是用字节来比较float类型大小时却需要注意这一点。b. 运算上溢的值不是实际值,而是特值 0 111,1111,0 000,0000,0000,0000,0000,0000 B,例如 1.0×2127 + 1.5×2127 不等于 1.5×2128,虽然它有能力表示1.5×2128。c. ㈢ 在C++中的部分解决方案及遗留问题5.参考资料《Inter 80X86/80387 汇编指南》6.附录[注1]:M$认为double精度已足够,故在MVC++5.0及以后取消80位了临时实数,令long double等同于double,但在本文中的long double还是指80位临时实数。[注2]:各种浮点类型格式类似,double指数偏移基数3FFH,long double指数偏移基数3FFFH,但long double特殊在无有效数字隐含位。[注3]:发表于 Thursday, May 20, 2004 5:59 AM 评论# re: float谈( ASM/C/C++,未完待续 ) 5/21/2004 4:37 AM Hunpo326 处理器不是采用了补码形式吗?这样还没有消除+0和-0问题呀。有点不明白,等我回头看看。 # to Hunpo326 5/21/2004 6:02 AM 周星星 对于整型才使用补码表示;看float的格式,如果使用补码表示负数只会带来麻烦。 # to 周星星 5/22/2004 5:02 AM Hunpo326 噢, 明白了 # to [xiong_107]: 5/25/2004 5:34 AM 周星星 double(1.000997) 在内存中的存储: double存储格式: 符号位1bit,阶码11bits,尾数52bits,还有一个隐含固定位 先将十进制表示的1.000997换算成二进制科学计数法表示,即 1.0000000001000001010101101110001001100100111001001000 乘以 2 的 0 次方, 第一bit是符号位,此时为正,故放0 接着是阶码,阶码此时为0,但要加上偏移基数3FFH,变成了01111111111(二进制表示) 接着是尾数,也就是小数点后面的52bits,小数点前面的1就不需要了,这就是隐含固定位的意义 这样就变成了0 01111111111 0000000001000001010101101110001001100100111001001000(二进制表示) 即 3FF004156E264E48(十六进制表示) # re: float谈( ASM/C/C++,未完待续 ) 6/8/2004 10:30 PM NoMatter The following parameters are used to define the model for each floating-point type: s sign (±1) b base or radix of exponent representation (an integer > 1) e exponent (an integer between a minimum emin and a maximum emax) p precision (the number of base-b digits in the significand) fk nonnegative integers less than b (the significand digits) A normalized floating-point number x ( f1 > 0 if x ≠ 0) is defined by the following model: p -k x = s × be ×Σ fk × b , emin ≤ e ≤ emax k=1

评论