C语言:浮点数在内存中的表示(转)

来源:互联网 发布:tpshop分销源码 编辑:程序博客网 时间:2024/05/16 09:47
C语言:浮点数在内存中的表示

单精度浮点数: 1位符号位   8位阶码位   23位尾数

双精度浮点数: 1位符号位   8位阶码位   52位尾数

 

实数在内存中以规范化的浮点数存放,包括数符、阶码、尾数。数的精度取决于尾数的位数。比如32位机上float型为23位       double型为52位。

单精度float型存储在内存中的大小为4个字节,即32位。

浮点表示的一般形式为:R=M*2^e (R:Real       M:Mantissa尾数     e:exponent阶码)

把上面float的二进制可分成三部分:

                    xxxxxxxx             xxxxxxxxxxxxxxxxxxxxxxx

数符(1b)         阶码(8b)         尾数(23b)

double型的浮点数分别是:数符(1b)、阶码(8b)、尾数(52b)

数符sign:real的正负号     "+":0        "-":1

阶码e:e=E-127(double型中e=E-1023) e为正值说明这个浮点数向左移动了e位, e为负值说明这个浮点数向右移动了e位。127=2^7-1 1023=2^10-1

尾数M:有效数字位,这里是有效数字位的部分二进制码

例1:float型浮点数125.5转化成32位二进制浮点数

125.5的二进制码为1111101.1,写成二进制的科学计数为:1.111101*2^6(因为科学计数法“整数”部分大于1,在二进制中,“整数”部分只能恒为1)即向左移6位,则e=6,则E=e+127=133,而E的二进制码为10000101,而1.111101把“整数”部分去除1之后为111101,之后补0,共23b,形成了阶码。

所以125.5的32位二进制浮点数为

0 10000101 11110100000000000000000

例2:float型浮点数0.5转化成32位二进制浮点数

0.5的二进制码为0.1,写成二进制的科学计数为:1.0*2^(-1)即向右移1位,则e=-1,则E=e+127=126,而E的二进制码为01111110,而1.0把“整数”部分去除1之后为0,之后补0,形成了阶码。

 

所以0.5的32位二进制浮点数为

0 01111110 00000000000000000000000

double型浮点数类似。

例3:32位二进制浮点数为0 10000010 00010000000000000000000转化成十进制数浮点数

题中已给我们分了三部分,数符部分、阶码部分、尾数部分。

数符部分为0,则代表此数为正数;阶码部分为10000010,则E=130,则e=E-127=3,则说明其向左移了3位,0001加上“整数”部分的1之后,为1.0001。则原二进制数为1000.1=十进制8.5,或R=1.0001*2^3=8.5

其中很多计算类似。可举一反三!

转自<http://blog.csdn.net/borefo/article/details/4620964>

由(int&)a引发的思考及浮点数在内存中的表示

今天看到一段代码,如下:请写出它的输出结果

#include<iostream>     

using namespace std;       

int main(void            

     float 1.0f;        

     cout << &a << endl;         

    cout << (int)&a << endl;         

    cout << (int&)a << endl;         

    cout << boolalpha << (int)a == (int&)a << endl;      

    float 0.0f;         

    cout << (int)b << endl;         

    cout << (int&)b << endl;         

    cout << boolalpha << (int)b == (int&)b << endl;         

    return 0; 

    

 

看到这段代码,一些概念性的东西一下就搞混了,(int&)a是什么含义呢?让我来看看输出结果:

0013FF60
1310560
1065353216
false
0
0
true

 

(int)&a 把a的地址强制转换成整型

(int&)a 把a强制转换成整形引用类型,相当于是某个整形引用,引向了a所在的32位内存区域,并将这32位当做一个整数。

(int)a a在内存中的值转换成int类型

   对于浮点数1.0,根据IEEE754的浮点数存储格式表示为3f800000(0011 1111 1000 0000 0000 0000 0000 0000),(int&)a把3f800000当做int型输出,所以结果为1065353216。

这里对float和double存储格式介绍一下:

C/C++的浮点数据类型有float和double两种。
 
类型float大小为4字节,即32位,内存中的存储方式如下: 
高地址<-------------------------------------->低地址
符号位     指数           尾数          |
1 bit     8 bit          23 bit         |
31<------>30<--------->22<---------------------->0

类型double大小为8字节,即64位,内存布局如下: 
高地址<---------------------------------------->低地址
符号位      指数            尾数          |
  1 bit     11 bit          52 bit         |
63<------>62<------------>51<--------------------->0

  
符号位决定浮点数的正负,0表示正,1表示负。 
指数和尾数均从浮点数的二进制科学计数形式中获取。 
如,十进制浮点数2.5的二进制形式为10.1,转换为科学计数法形式为(1.01)*(21),由此可知指数为1,尾数(即科学计数法的小数部分)为01。 
根据浮点数的存储标准(IEEE制定),float类型指数的起始数为127(二进制0111 1111),double类型指数的起始数为1023(二进制011 1111 1111),在此基础上加指数,得到的就是内存中指数的表示形式。尾数则直接填入,如果空间多余则以0补齐,如果空间不够则0舍1入。所以float和double类型分别表示的2.5如下(二进制): 
float
|符号位|    指数             尾数
  | 1000 0000 | 010 0000 0000 0000 0000 0000 
double
|符号位|      指数                    尾数
  | 100 0000 0000 | 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

浮点数2.5可以用二进制小数准确表示(2.5=1*(21)+0*(20)+1*(2-1)),但很多小数不可以准确表示,其二进制形式的小数部分会无限循环,如浮点数-1.2表示如下(二进制): 
float
|符号位|    指数             尾数        
  | 0111 1111 |  0011 0011 0011 0011 0011 010  
double
|符号位|       指数                   尾数 
  | 011 1111 1111 | 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011

    由于对无限循环尾数的截取遵循0舍1入,尾数的第21~24位为0011,第53~56位为0011,而float尾数容量为23位,double尾数容量为52位,所以,float形式的最后三位因进位而成010,double形式则没有进位发生。 
    类型float和double通过==,>,<等比较不会引起编译错误,但是非常可能得到错误的结果。这是因为它们的内存分布不同,不可以直接比较。正确的方法是转换为同一类型后比较两者差值,如果结果小于规定的小值,则视为相等。

ps:
1) IEEE浮点数标准:   
4字节浮点数:1位符号位,8位阶数(基数为127的移码),23位尾数;
8字节浮点数:1位符号位,11位阶数(基数为1023的移码),52位尾数

2 ) 在VC中: float数值范围约在 -10e38~10e38,并提供7位有效数字位,绝对值小于10e38地数被处理成零值 double数值范围约在-10e308~10e308,并提供15~16位有效数字,绝对值小于10e308地数被处理成零值

原创粉丝点击