首页 > C > 数据类型与变量 阅读:57,774

浮点型

< 上一页 整型 C程序中的数据类型 下一页 >

C语言里,实数的类型有单精度float类型和双精度double类型。其中double类型表示的实数精度比单精度的类型要高。

在计算机系统的发展过程中,曾经提出过多种方法表示实数,但是到目前为止使用最广泛的是浮点表示法。相对于定点数而言,浮点数利用指数使小数点的位置可以根据需要而上下浮动,从而可以灵活地表达更大范围的实数。

         float x = 0.3555f;//定义了一个单精度浮点数,对于单精度实数常量后面需要带一个f

         double y = 0.3555;//定义了一个双精度浮点数

上面的2句话在程序里的意思是:第一句,定义了一个单精度实数变量x,并把一个实数0.3555f赋值给该变量x,此时x的值就是0.3555;第二句,定义了一个双精度变量y,并把一个实数0.3555赋值给该变量y,此时y的值就是0.3555

    目前C/C++编译器标准都遵照IEEE制定的浮点数表示法来进行floatdouble运算。这种结构是一种科学计数法,用符号、指数和尾数来表示,底数定为2——即把一个浮点数表示为尾数乘以2的指数次方再添上符号。下面是具体的规格:

    

 

符号位

阶码

尾数

长度

float

1

8

23

32

double

1

11

52

64

    由于通常C编译器默认浮点数是double型的,下面以double为例:

共计64位,折合8字节。由最高到最低位分别是第636261、……、0位。最高位63位是符号位,1表示该数为负,0正;62-52位,一共11位是指数位;51-0位,一共52位是尾数位。

按照IEEE浮点数表示法,下面将把double型浮点数38414.4转换为十六进制代码。 把整数部和小数部分开处理:整数部直接化十六进制:960E。小数的处理:

    0.4=0.5*0+0.25*1+0.125*1+0.0625*0+……

实际上这永远算不完!这就是著名的浮点数精度问题。所以直到加上前面的整数部分算够53位就行了(隐藏位技术:最高位的1不写入内存)。

如果你够耐心,手工算到53位那么因该是:38414.4(10)=1001011000001110.0110101010101010101010101010101010101(2)

科学记数法为:1.001……乘以215次方。指数为15。于是来看阶码,一共11位,可以表示范围是-1024   ~   1023。因为指数可以为负,为了便于计算,规定都先加上1023,在这里,15+1023=1038。二进制表示为:100   00001110

符号位:正,0。合在一起(尾数二进制最高位的1不要):

    01000000   11100010   11000001   11001101   01010101   01010101   01010101   01010101

按字节倒序存储的十六进制数就是: 55   55   55   55   CD   C1   E2   40

    首先了解一下实数的表示和存储。计算机中的实数一般是通过浮点数的形式来表示的。浮点数的主要特点是让小数点的位置根据需要而浮动,它既能表示整数又能表示小数,并且小数部分的位数可以变化。浮点数据表示的基本原理来源于十进制数中的科学记数法。

一个浮点数包含:符号,小数和指数,其形式可写成:

 

其中M为尾数(用纯小数来表示,所谓纯小数,即为没有整数部分的小数,R为底数(常为2),E为阶码(指数)。比如:f = 0.123456 * 29

一个带符号的float的内存结构体描述如下:

 

typedef struct _float

{

  bool bSign : 1; // 符号,表示正负,1

  char cExponent : 8; // 指数,8

  unsigned long ulMantissa : 23; // 尾数,23

} float;

typedef struct _double

{

  bool bSign : 1; // 符号,表示正负,1

  char cExponent : 11; // 指数,11

  unsigned long ulMantissa : 52; // 尾数,52

} double;

 

它的存储结构如图3-13所示:

 

 

 

                                                        3-13 实数floatdouble的存储

用来表示尾数的位数越多,表示实数的精度越大。指数占多少位,尾数占多少位,由计算机系统决定。对编程人员来说,double  float 的区别是double精度高,但double消耗内存是float的两倍。程序员都更喜欢用double而不是float

以下通过程序的方式把浮点数在计算机内的表示方式输出:

 

int func(float fval)

{

    char *p, tmp;

    int i, j, t;

 

    float fvalue = fval;

    p = (char *)&fvalue;

    for (i = sizeof(float)-1; i >= 0; i--)

    {

        t = 0x80;

        tmp = *(p+i);

        for (j = 0; j < 8; j++)

       {

            if (tmp&t)

                printf("1");

            else

                printf("0");

            t >>= 1;

        }

        printf("\n");

    }

    return 0;

}

 

实数存储格式计算,以计算178.125为例子,试着计算它在内存中的存储格式如下,共分为3步:

 

第一步:178.125表示成二进制数:(178.125)(十进制数)=(10110010.001)(二进制形式);

第二步:将二进制形式的浮点实数转化为规格化的形式:(小数点向左移动7个二进制位可以得到)

10110010.001=1.0110010001*2^7 因而产生了以下三项:

符号位:该数为正数,故第31位为0,占一个二进制位.

阶码:指数(e)7,故其阶码为127+7=134=(10000110)(二进制),占从第30到第238个二进制位.

(注:指数有正负即有符号数,但阶码为正即无符号数,所以将e加个127作为偏移,方便指数的比较)

尾数为小数点后的部分0110010001.因为尾数共23个二进制位,在后面补130,01100100010000000000000

第三步:将符号位,阶码,尾数结合在一起,所以,178.125单精度浮点数在内存中的实际表示方式为:

0 10000110 01100100010000000000000

< 上一页 整型 C程序中的数据类型 下一页 >

周哥教IT,分享编程知识,提高编程技能,程序员的充电站。跟着周哥一起学习,每天都有进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

当你决定关注「周哥教IT」,你已然超越了90%的程序员!

IT黄埔-周哥教IT技术交流QQ群:213774841,期待您的加入!

二维码
微信扫描二维码关注