http://www.cnblogs.com/onedime/archive/2012/11/19/2778130.html

http://blog.csdn.net/adream307/article/details/7246993

http://wenku.baidu.com/link?url=Q_SYeQffEjdS1cpMXIRncmmhwKA_o2978-0ei1_gz9ym2vrmmBrSEZArpE6tR4yCB9PEHLG_FHRakijbr9-Y0DIK_MTjBUTKoXUhgIYETB3

ZC:

    float f;
int j = 0x7FFFFFFF;
memcpy(&f, &i, sizeof(i));

一、

浮点型变量在计算机内存中占用4字节(Byte),即32-bit。遵循IEEE-754格式标准。
一个浮点数由2部分组成:底数m 和 指数e。
                          ±mantissa × 2exponent
(注意,公式中的mantissa 和 exponent使用二进制表示)
底数部分 使用2进制数来表示此浮点数的实际值。
指数部分 占用8-bit的二进制数,可表示数值范围为0-255。 但是指数应可正可负,所以IEEE规定,此处算出的次方须减去127才是真正的指数。所以float的指数可从 -126到128.
底数部分实际是占用24-bit的一个值,由于其最高位是e位 ,所以最高位省去不存储,在存储中只有23-bit。
到目前为止, 底数部分 23位 加上指数部分 8位 使用了31位。那么前面说过,float是占用4个字节即32-bit,那么还有一位是干嘛用的呢?   还有一位,其实就是4字节中的最高位,用来指示浮点数的正负,当最高位是1时,为负数,最高位是0时,为正数。
   浮点数据就是按下表的格式存储在4个字节中:
                    Address+0       Address+1              Address+2              Address+3
Contents     SEEE EEEE     EMMM MMMM     MMMM MMMM     MMMM MMMM      S: 表示浮点数正负,1为负数,0为正数
      E: 指数加上127后的值的二进制数
      M: 24-bit的底数(只存储23-bit)
主意:这里有个特例,浮点数 为0时,指数和底数都为0,但此前的公式不成立。因为2的0次方为1,所以,0是个特例。当然,这个特例也不用人为去解决,编译器会自动去识别。

通过上面的格式,我们下面举例看下4.5在计算机中存储的具体数据:
                    Address+0                 Address+1               Address+2            Address+3
Contents        0x40                         0x90                           0x00                      0x00     接下来我们验证下上面的数据表示的到底是不是4.5,从而也看下它的转换过程。
由于浮点数不是以直接格式存储,他有几部分组成,所以要转换浮点数,首先要把各部分的值分离出来。
                  Address+0      Address+1                  Address+2             Address+3
格式         SEEEEEEE     EMMMMMMM       MMMMMMMM     MMMMMMMM
二进制     01000000         10010000               00000000                00000000
16进制     40                         90                            00                            00
       可见:
       S: 为0,是个正数。
       E:为 10000001   转为10进制为129,129-127=2,即实际指数部分为2。
       M:为 00100000000000000000000。 这里,在底数左边省略存储了一个1,使用 实际底数表示为 1.00100000000000000000000
       到此,我们吧三个部分的值都拎出来了,现在,我们通过指数部分E的值来调整底数部分M的值。调整方法为:如果指数E为负数,底数的小数点向左移,如果指数E为正数,底数的小数点向右移。小数点移动的位数由指数E的绝对值决定。
      这里,E为正2,使用向右移2为即得:
      100.100000000000000000000
至次,这个结果就是4.5的二进制浮点数,将他换算成10进制数就看到4.5了,如何转换,看下面:
小数点左边的100 表示为 (1 × 22) + (0 × 21) + (0 × 20), 其结果为 4。
小数点右边的 .100… 表示为 (1 × 2-1) + (0 × 2-2) + (0 × 2-3) + ... ,其结果为.5 。
以上二值的和为4.5, 由于S 为0,使用为正数,即4.5 。
所以,16进制 0x40900000 是浮点数 4.5 。

上面是如何将计算机存储中的二进制数如何转换成实际浮点数,下面看下如何将一浮点数装换成计算机存储格式中的二进制数。
举例将17.625换算成 float型。
首先,将17.625换算成二进制位:10001.101   ( 0.625 = 0.5+0.125, 0.5即 1/2, 0.125即 1/8 如果不会将小数部分转换成二进制,请参考其他书籍。) 再将 10001.101 向右移,直到小数点前只剩一位 成了 1.0001101 x 2的4次方(因为右移了4位)。此时 我们的底数M和指数E就出来了:
底数部分M,因为小数点前必为1,所以IEEE规定只记录小数点后的就好,所以此处底数为   0001101 。
指数部分E,实际为4,但须加上127,固为131,即二进制数 10000011 
符号部分S,由于是正数,所以S为0.
综上所述,17.625的 float 存储格式就是:
0 10000011 00011010000000000000000
转换成16进制:0x41 8D 00 00
所以,一看,还是占用了4个字节。

二、

float一共32位,其结构定义如下:

|-------- 31 -------|------------ 30-23 ------------ |------------ 22-0 ------------|

符号位(sign)         指数部分(exp)                       小数部分(mag)

sign:符号位就一位,0表示正数,1表示负数

exp: 指数部分,无符号正数

mag:小数部分,定点小数,小数点在最左边。

float的表达式 :  pow(-1,sign)  *  (1+mag)  * pow(2,exp-127)

#include <stdio.h>
#include <stdlib.h>
#include <math.h> int main(int argc,char *argv[])
{
float f;
int i;
int sign;
int exp;
int mag;
float d_mag;
float f2; sscanf(argv[],"%f",&f);
//f=-0.12;
i = *(int*)&f;
sign = (i>>)&0x01;
exp = (i>>)&0xFF;
mag = i&0x7FFFFF;
d_mag = 1.0f*mag/0x800000;
f2 = (sign==?:-)*(+d_mag)*pow(,exp-);
printf("float:f=%f\n",f);
printf("sign=%X,exp=%X,mag=%X\n",sign,exp,mag);
printf("float:f2=%f\n",f2);
return ;
}

参考文献:http://en.wikipedia.org/wiki/IEEE_754-1985

三、

进制的算法:

整数

整数的二进制算法大家应该很熟悉,就是不断的除以

2

取余数,然后将余数倒序排

列。

小数

小数的二进制算法和整数的大致相反,就是不断的拿小数部分乘以

2

取积的整数部

分,然后正序排列。比如求

0.9

的二进制:

0.9*2=1.8

1

0.8*2=1.6

1

0.6*2=1.2

1

0.2*2=0.4

0

0.4*2=0.8

0

0.8*2=1.6

1

… …

如此循环下去。因此我么得到的二进制小数也是无限循环的:

0.11100110011...

从小数的二进制算法中我们可以知道,如果想让这种算法停止,只有在小数部分是

0.5

的时候才可以,但是很不幸,这类的小数很少。所以大部分小数是很难用二进制

来精确表示的。

 

------------------------

我是分割线

------------------------------

OK

,有了上面的知识,我们进入正题:看看

float

类型在内存中是如何表示的。

 

float

类型又称为单精度浮点类型,在

 
 

IEEE 754-2008

 
 

中是这样定义它的结构的:

 

S

 

EEEEEEEE

 

FFFFFFFFFFFFFFFFFFFFFFF

 

31

30

23

22

0

 

float

类型总共

4

个字节

——

32

位:

1.

符号位

其中最左边的为符号位,

0

为正,

1

为负。

2.

指数

接下来的

E

是指数,一共

8

位,也用二进制来表示。

3.

尾数

最后的

F

是小数部分,

尾数正是由这

23

位的小数部分

+1

位组成的。

这个稍后解释)

 

这里我们需要多说一下指数。虽然指数也是用

8

位二进制来表示的,但是

IEEE

在定义它的时候

做了些手脚,使用了偏移来计算指数。

 
 

IEEE

 

规定,在

 

float

 

类型中,用来计算指数的偏移量为

127

 

。也就是说,如果你的指数实际是

0

 

 

那么在内存中存的就是

 

0+127=127

 

的二进制。稍后我们来看这个到底如何使用。

 
 
 

好了,看了这么多,我们该演示一下计算机如何将一个十进制的实数转换为二进制的。就拿

 

6.9

 

这个数字来举例吧。

 

-_-||!

 
 
 

首先,我们按照上面说的方法,分别将整数和小数转换成对应的二进制。这样

6.9

 

的二进制表示

 

就是

 

110.1110011001100...

。这里就看出来了,

 

6.9

 

转换成二进制,小数部分是无限循环的,这在

 

现在的计算机系统上是无法精确表示的。这是计算机在计算浮点数的时候常常不精确的原因之

 

一。

 
 

其次,将小数点左移(或右移)到第一个有效数字之后。说的通俗些,就是把小数点移到第一个

 

1

之后。这样的话,对于上面

 

 

110.1110011001100...

 

我们就需要把小数点左

 

2

 

位,得到

 

1.101110011001100...

 

 
 
 

接下来的事情就有意思了。

首先我们把得到的

 

1.101110011001100..

这个数,

 

从小数点后第一位开

 

始,数出

 

23

 

个来,填充到上面

 

float

内存结构的尾数部分(就是那一堆

 

F

 

的地方),我们这里数

 

出来的就是

 

10111001100110011001100

。这里又要发生一次不精确了,小数点后超出

 
 

23

 

位的部

分都将被舍弃,太惨了。

 
 
 

不过,

 

这里有一个可能让大家觉得特别坑爹的事情,

 

就是小数点前面的

 

1

 

也不要了。仔细看看上

面的内存结构,确实没有地方存放这个

 

1

 

。原因是这样的:

 

IEEE

 

觉得,既然我们大家都约定把

 

小数点移动到第一个有效数字之后,那也就默认小数点前面一定有且只有一个

1

 

,所以把这个

 

1

 

存起来也浪费,干脆就不要了,以后大家都这么默契的来就好。这也是为什么我上面说尾数是

 

23

 

 

+1

位的原因。

 
 
 

填充完尾数,

 

该填充指数了。

这个指数就是刚才我们把小数点移动的位数,

 

左移为正,

 

右移为负,

 

再按照上面所说的偏移量算法,我们填充的指数应该是

 

2+127=129

 

。转换成

8

 

位二进制就是

10000001

 

 
 

最后,根据这个数的正负来填充符号位。我们这里是正数,所以填

 

0

 

。这样

 

6.9

 

的在内存中的存

 

储结果就出来了:

 
 
 

0

10000001

10111001100110011001100

总结一下,实数转二进制

float

类型的方法:

A.

分别将实数的整数和小数转换为二进制

B.

左移或者右移小数点到第一个有效数字之后

C.

从小数点后第一位开始数出

23

位填充到尾数部分

D.

把小数点移动的位数,左移为正,右移为负,加上偏移量

127

,将所得的和转换为二进制填

充到指数部分

E.

根据实数的正负来填充符号位,

0

为正,

1

为负

如果需要把

float

的二进制转换回十进制的实数,只要将上面的步骤倒着来一边就行了

【转】float类型在内存中的表示的更多相关文章

  1. long类型在内存中占8个字节,float类型在内存中占4个字节,为什么long还要比float小呢?

    结论:数值范围大小和占用的字节没有关系. float类型的范围: 负数:-3.402823E38~-1.401298E-45 整数:0 正数:1.401298E-45~3.402823E38 long ...

  2. C语言中float,double类型,在内存中的结构(存储方式)

    C语言中float,double类型,在内存中的结构(存储方式)从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以doubl ...

  3. float数据在内存中是怎么存储的 AND IEEE754测试程序

    float类型数字在计算机中用4个字节存储.遵循IEEE-754格式标准: 一个浮点数有2部分组成:底数m和指数e 底数部分 使用二进制数来表示此浮点数的实际值指数部分 占用8bit的二进制数,可表示 ...

  4. 牛客网Java刷题知识点float数据在内存中是怎么存储的

    不多说,直接上干货! float类型数字在计算机中用4个字节存储. 遵循IEEE-754格式标准: 一个浮点数有2部分组成:底数m和指数e (1)底数部分 使用二进制数来表示此浮点数的实际值 (2)指 ...

  5. float数据在内存中存储方式

    float类型数字在计算机中用4个字节存储.遵循IEEE-754格式标准: 一个浮点数有3部分组成: 符号部分,0 表示正,1表示负. 底数部分 使用二进制数来表示此浮点数的实际值,底数部分实际是占用 ...

  6. PHP对象类型在内存中的分配

    对象类型和整型.字符串等类型一样,也是PHP中的一种数据类型.都是在程序中用于存储不同类型数据使用的,在程序运行时它的每部分内容都要先加载到内存中再被使用.那么对象类型的数据在内存中是如何分配的呢?先 ...

  7. float数据在内存中的存储方法

    浮点型变量在计算机内存中占用4字节(Byte),即32-bit.遵循IEEE-754格式标准.一个浮点数由2部分组成:底数m 和 指数e.                          ±mant ...

  8. JavaScript 变量类型 保存内存中的位置 和 引用

    1. JavaScript变量 基本类型值在内存中占据固定大小的空间 因此被保存在栈内存中. 从一个变量向另一个变量复制基本来下的值 会创建这个值得一个副本. 引用类型的值是对象 保存在堆内存中. 包 ...

  9. 打印出C# 中float ,double 在内存中的存放形式

    float floatA = 2.2f; ); ; i < ;++i ) { uint temp = 0x80000000 & (a << i); ) { Console.W ...

随机推荐

  1. SQL Expression Language Tutorial 学习笔记二

    11. Using Textual SQL 直接使用 SQL 如果实在玩不转, 还是可以通过 test() 直接写 SQL. In [51]: s = text( ...: "SELECT ...

  2. testng入门教程6 TestNG忽略测试

    有时,我们的代码是没有准备好,如果测试用例写入到测试方法/代码将无法运行,在这种情况下,@Test(enabled = false)有助于禁用此测试案例. 测试方法是标注了@Test(enabled ...

  3. RocketMQ 2主2从 集群搭建

    安装环境 jdk1.7 alibaba-rocketmq-3.2.6.tar.gz VM虚拟机redhat6.5-x64:192.168.1.201  192.168.1.202 192.168.1. ...

  4. linux常用命令:df 命令

    linux中df命令的功能是用来检查linux服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 1.命令格式: df [选项] [文件] 2.命 ...

  5. web前端----html表单操作

    form表单 功能:表单用于向服务器传输数据,从而实现用户与Web服务器的交互 表单能够包含input系列标签,比如文本字段.复选框.单选框.提交按钮等等. 表单还可以包含textarea.selec ...

  6. Notes of Head.First.HTML.and.CSS.2nd.Edition

    What does the web server do? tirelessly waiting for requests from webbrowsers What does the web brow ...

  7. UVA302 John's trip(欧拉回路)

    UVA302 John's trip 欧拉回路 attention: 如果有多组解,按字典序输出. 起点为每组数据所给的第一条边的编号较小的路口 每次输出完额外换一行 保证连通性 每次输入数据结束后, ...

  8. lambda表达式Bug——修改捕获变量失败

    解<C++ Primer 5th>的 9-50 练习题时,遇到了 lambda表达式值捕获和引用捕获之区别问题. 欲修改捕获的变量 sum,累加之.但当时忘记值捕获和引用捕获是有区别的.下 ...

  9. 20145118《Java程序设计》 第9周学习总结

    20145118 <Java程序设计>第9周学习总结 教材学习内容总结 1.SUN公司定义了一套Java操作数据库的规范(接口)来简化数据库操作,称之为JDBC.开发人员只需要学习jdbc ...

  10. 20165211 2017-2018-2 《Java程序设计》第2周学习总结

    20165211 2017-2018-2 <Java程序设计>第2周学习总结 教材学习内容总结 本周,我学习了书本上二三两章的内容,以下是我整理的主要知识 第二章 基本数据类型与数 标识符 ...