浮点数浮点数是属于有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意某个实数。
具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学记数法。
浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。
一个浮点数a由两个数m和e来表示:a = m ×b^e。
在任意一个这样的系统中,我们选择一个基数b(记数系统的基)和精度p(即使用多少位来存储)。
m(即尾数)是形如±d.ddd...ddd的p位数(每一位是一个介于0到b-1之间的整数,包括0和b-1)。
如果m的第一位是非0整数,m称作规格化的。
有一些描述使用一个单独的符号位(s 代表+或者-)来表示正负,这样m必须是正的。
e是指数。
由此可以看出,在计算机中表示一个浮点数,其结构如下:这种设计可以在某个固定长度的存储空间内表示定点数无法表示的更大范围的数。
例如,一个指数范围为±4的4位十进制浮点数可以用来表示43210,4.321或0. 0004321,但是没有足够的精度来表示432.123和43212.3(必须近似为432.1和4 3210)。
当然,实际使用的位数通常远大于4。
此外,浮点数表示法通常还包括一些特别的数值:+∞和−∞(正负无穷大)以及NaN('Not a Number')。
无穷大用于数太大而无法表示的时候,NaN则指示非法操作或者无法定义的结果。
众所周知,计算机中的所有数据都是以二进制表示的,浮点数也不例外。
然而浮点数的二进制表示法却不像定点数那么简单了。
先澄清一个概念,浮点数并不一定等于小数,定点数也并不一定就是整数。
所谓浮点数就是小数点在逻辑上是不固定的,而定点数只能表示小数点固定的数值,具用浮点数或定点数表示某哪一种数要看用户赋予了这个数的意义是什么。
C++中的浮点数有6种,分别是:float:单精度,32位unsigned float:单精度无符号,32位double:双精度,64位unsigned double:双精度无符号,64位long double:高双精度,80位unsigned long double:高双精度无符号,80位(嚯,应该是C++中最长的内置类型了吧!)然而不同的编译器对它们的支持也略有不同,据我所知,很多编译器都没有按照IEEE规定的标准80位支持后两种浮点数的,大多数编译器将它们视为double,或许还有极个别的编译器将它们视为128位?!对于128位的long double我也仅是听说过,没有求证,哪位高人知道这一细节烦劳告知。
下面我仅以float(带符号,单精度,32位)类型的浮点数说明C++中的浮点数是如何在内存中表示的。
先讲一下基础知识,纯小数的二进制表示。
(纯小数就是没有整数部分的小数,讲给小学没好好学的人)纯小数要想用二进制表示,必须先进行规格化,即化为 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。
对于一个纯小数D,求n的公式如下:n = 1 + log2(D); // 纯小数求得的n必为负数再用 D / ( 2 ^ n ) 就可以得到规格化后的小数了。
接下来就是十进制到二进制的转化问题,为了更好的理解,先来看一下10进制的纯小数是怎么表示的,假设有纯小数D,它小数点后的每一位数字按顺序形成一个集合:{k1, k2, k3, ... , kn}那么D又可以这样表示:D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )推广到二进制中,纯小数的表示法即为:D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )现在问题就是怎样求得b1, b2, b3,……,bn。
算法描述起来比较复杂,还是用数字来说话吧。
声明一下,1 / ( 2 ^ n )这个数比较特殊,我称之为位阶值。
例如0.456,第1位,0.456小于位阶值0.5故为0;第2位,0.456大于位阶值0.25,该位为1,并将0.45减去0.25得0.206进下一位;第3位,0.206大于位阶值0.125,该位为1,并将0.206减去0.125得0.081进下一位;第4位,0.081大于0.0625,为1,并将0.081减去0.0625得0.0185进下一位;第5位0.0185小于0.03125……最后把计算得到的足够多的1和0按位顺序组合起来,就得到了一个比较精确的用二进制表示的纯小数了,同时精度问题也就由此产生,许多数都是无法在有限的n 内完全精确的表示出来的,我们只能利用更大的n值来更精确的表示这个数,这就是为什么在许多领域,程序员都更喜欢用double而不是float。
float的内存结构,我用一个带位域的结构体描述如下:struct MYFLOAT{bool bSign : 1; // 符号,表示正负,1位char cExponent : 8; // 指数,8位unsigned long ulMantissa : 23; // 尾数,23位};符号就不用多说了,1表示负,0表示正指数是以2为底的,范围是-128 到127,实际数据中的指数是原始指数加上1 27得到的,如果超过了127,则从-128开始计,其行为和X86架构的CPU处理加减法的溢出是一样的。
比如:127 + 2 = -127;-127 - 2 = 127尾数都省去了第1位的1,所以在还原时要先在第一位加上1。
它可能包含整数和纯小数两部分,也可能只包含其中一部分,视数字大小而定。
对于带有整数部分的浮点数,其整数的表示法有两种,当整数大于十进制的16777215时使用的是科学计数法,如果小于或等于则直接采用一般的二进制表示法。
科学计数法和小数的表示法是一样的。
小数部分则是直接使用科学计数法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n )。
拆开来看。
0 00000000 0000000000000000000000符号位指数位尾数位关于浮点数的表示悬赏分:0 - 解决时间:2009-5-20 17:40我刚刚开始认真学浮点数的表示看到这个那么这个最大值就是:0 11111110 11111111111111111111111。
也就是2(254-127) * (1.11111111111111111111111)2 = 2127 * (1+1-2-23) =3.40282346638529E+38下面那个式子是什么意思按第一个表示的方法整数应该是11111110的十进制小数应该是11111111111111111111111的十进制才对啊请各位帮帮解答一下如果我搞懂了再多的分也没关系谢谢了问题补充:在线等噢`根据上面的约定,我们可以知道阶码P的最大值是11111110(这个值是254,因为255用于特殊的约定,那么对于可以精确表示的数来说,254就是最大的阶码了)。
尾数的最大值是11111111111111111111111。
那么这个最大值就是:0 11111110 11111111111111111111111。
也就是2(254-127) * (1.11111111111111111111111)2 = 2127 * (1+1-2-23) =3.40282346638529E+38从上面的双精度表示可以看出,两者是一致的。
最小的数自然就是-3.40282346638529E+38。
对于最接近于0的数,根据IEEE754的约定,为了扩大对0值附近数据的表示能力,取阶码P = -126,尾数M = (0.00000000000000000000001)2 。
此时该数的二进制表示为:0 00000000 00000000000000000000001也就是2-126 * 2-23 = 2-149 = 1.40129846432482E-45。
这个数字和上面的Epsilon是一致的。
如果我们要精确表示最接近于0的数字,它应该是0 00000001 00000000000000000000000也就是:2-126 * (1+0) = 1.17549435082229E-38。
这些是这一部分原文提问者:yuqangy - 职场新人三级最佳答案请注意:首先阶码和尾数都有符号位阶码:0 1111110 符号位为0,所以是正得值为254这里注意这个254不是最后阶码值,根据7.54规定偏正值为127,也就是每次阶码值都要减去127才是最后得阶码值.这里为什么要减去127,是因为这里采用无符号数存放得,而这里本该是有符号数-126-127,因为无符号数便于比较所以通通+127,阶码就成了1-254.然后在存入计算机.所以这里你得到254是+127后的无符号数,所以先减去127还原成有符号数.尾数:0 11111111111111111111111,符号是0.这里要注意有规格化浮点数规定.规格化浮点数如果符号位和最高位异号会省掉一位尾数.这里就省掉了一位尾数.也就是说此时是1.11111111111111111111111。
举个例子比如尾数是1.1111他会存为0 1111 省掉了最高位1.所以尾数是1.1111.现在明白了吧./view/1698149.htm这里有IEE7.54规范可以去参考下.给我加分哦!~~~~~~~~~~~~~~~~单精度浮点数的存储格式符号指数尾数+-+--------+-----------------------+|S| E | M |+-+--------+-----------------------+31 30....23 22....................0 ←位序号</pre>其代表的真实的数值为 (-1)S*2e*m 其中e,m分别为E,M对应的实际数值,而E,M 仅仅是一串二进制位。
符号位S(sign) - 1bit0代表正号,1代表负号。
(+0、-0视为相同?(欢迎补充资料))指数位E(exponent) - 8bitE的取值范围为0-255(无符号整数),实际数值e=E-127。
有时E也称为“移码”,或不恰当的称为“阶码”(阶码实际应为e)尾数位M(mantissa) - 23bitM也叫有效数字位(sinificand)、系数位(coefficient), 甚至被称作“小数”。
在一般情况下,m=(1.M)2,使得实际起作用范围为1≤尾数<2。
为了对溢出进行处理,以及扩展对接近0的极小数值的处理能力,IEEE 754对M做了一些额外规定,参见后文介绍。