研究了一下浮点型在内存中的表示方法,终于明白fortify果然不是吃素的,原来double型数字真的有可能超过200位的。。
一、浮点型在内存中的表示
单精度float型: 1位符号位, 8位阶码(固定偏移 7F), 尾数23, 固定隐含位有
双精度double型: 1位符号位, 11位阶码(固定偏移 3FF), 尾数52, 固定隐含位有
long double型: 1位符号位, 15位阶码(固定偏移3FFF), 尾数64, 固定隐含位无
某些编译器中把long double作double处理
其中,
符号位s:0表示正,1表示负;
阶码e:表示指数,需要减去固定偏移de;
尾数x:表示纯小数位,固定隐含位z是指整数位的1或者0。
表示成十进制就是(-1)^s * 2^(e-de) * (z+x)
对于32位系统,float占32位,double占64位
举例来说,在BIG ENDIAN中二进制表示为01000001 00100000 00000000 00000000的浮点数,根据上面的规则,可以写成:
0,10000010,0100000 000000000 0000000
符号位s=0,阶码e=10000010b=130,固定偏移de=0x7F=127,尾数x=0.01000000000000000000000b=0.25,固定隐含位有,z=1
根据公式可以算出这个数的十进制表示为:(-1)^0 * 2^(130-127) * (1+0.25) = 10.0
二、一些特殊的浮点数
0,00000000,0000000 00000000 00000000和1,00000000,0000000 00000000 00000000均表示0(阶码和尾数都是0)
*,11111111,******* ******** ******** 表示非法数字(阶码是255时)
最大的float数:0,11111110,1111111 11111111 11111111 用10进制表示约为 +3.4e38
最小的float数:1,11111110,1111111 11111111 11111111 用10进制表示约为 -3.4e38
绝对值最小的float数:0,00000000,0000000 00000000 00000001和1,00000000,0000000 00000000 00000001
三、浮点数的精度
单精度数的尾数用23位存储,加上默认的小数点前的1位1,2^(23+1) = 16777216。因为 10^7 < 16777216 < 10^8,所以说单精度浮点数的有效位数是7位。
双精度的尾数用52位存储,2^(52+1) = 9007199254740992,10^16 < 9007199254740992 < 10^17,所以双精度的有效位数是16位。
如果你在浮点数的有效位后增加数字的话,结果是不会变化的。
四、浮点数的取值范围
float取值范围:
负数取值范围为 -3.4028235E+38 到 -1.401298E-45,正数取值范围为 1.401298E-45 到 3.4028235E+38。
double取值范围:
负值取值范围-1.79769313486231570E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.79769313486231570E+308。
所以说,double型在sprintf的时候,要么想办法回避Buffer Overflow的问题,要么就...给字符数组分配308以上的空间...
posted on 2010-02-11 23:49
RayRiver 阅读(990)
评论(0) 编辑 收藏 引用 所属分类:
C/C++