IEEE浮点数float、double的存储结构

众所周知,C的float、VB的Single都是32位浮点数变量类型(也叫单精度浮点数),C的double和VB的Double则都是64位的浮点数变量类型(也叫双精度浮点数)。有些编译器还支持更屌的long double(貌似是80位还是128位的我不清楚,总之存在这种变态玩意儿。)那么这些浮点数从最底层的角度来看,它们是怎么存储的呢?我来举个例子解释下。计算机用的是二进制,如果我用二进制跟大家解释大家可能觉得看不懂,那我就用十进制来跟大家解释。
浮点数分三个部分,第一个部分是有效数字,第二个部分给出小数点的位置,第三个部分用来判断这个数是正数还是负数。举例如下:
浮点数123.456
那么它用浮点数的存储格式来表示就是:有效数字就是123456,小数点的位置在3的后面,然后它是正数。

那么我们要做的就是先取出有效数字123456,然后在3的后面插入小数点.就成了123.456,最后给它加个正号,就是+123.456了。

从二进制的方面来理解也是一样的,比如我要表示-10101010.01010101,那么它的有效数字是1010101001010101,小数点在中间,然后它是负数。
上面我都只说了“小数点在中间”、“小数点在3后面”这种比较含糊的表达方法。那么浮点数到底是怎么存储小数点的位置呢?这里我们要注意一整个浮点数中用来表示小数点位置的位数是多少。
还是用十进制来给大家举个例子。假设我用两个位来表示小数点的位置,那么两个十进制位表示的最小的数是00,最大的数是99,我们总共能表达100个值。假设我要表达1234.5678,那么情况就是如下所示的:
有效数字是12345678
小数点的位置在中间。
这里我们用两个十进制位来表示小数点的位置,那么这个小数点从左往右数(原来的数字是1234.5678)是在第四个位的后面。因此这两个十进制位的值就是03。因为00表示从左往右数的第一个位的后面,01表示从左往右数的第二个位的后面,02表示从左往右数的第三个位的后面,那么03就表示从左往右数的第四个位的后面了。
有人可能会说“但是这样一来我们不就无法表现小数了嘛。”其实不然。比如我们要表现0.233,那么我们就把有效数字设置成“0233”,然后小数点位置是00就行了。
对应的,二进制表示也是这样的,比如我们用8个二进制位来表示小数点的位置,我们要表现的小数是10101010.01010101,那么小数点在从左往右数第八个位的后面,我们就用00001000来表示小数点的位置。

这里我就需要针对性地告诉大家,float和double是怎么回事。
float浮点数的有效数字是23位,小数点用8个位表示,然后符号(正、负)用一个位表示(0表示正、1表示负),总共组成32位。
因为float浮点数用8个位表示小数点的位置,因此小数点可以有256个位置。float浮点数规定从左往右数第127位的值必须是1,然后从第128位开始才是float的23位有效数字。因此float的浮点数的23位有效数字其实是从左往右数从第128位开始的。
我这里举个例子:浮点数1.0f是怎么存储的:
0 01111111 00000000000000000000000(0x3F800000)
其中蓝色的部分是符号位,0表示正数。
黄色的部分表示小数点的位置,在从左往右数第127位处。
绿色部分是有效数字,共23个0,也就是全零。如果转换为十进制,大约就是6、7个数位左右。
按照float浮点数的特性,第127位的值必须是1,然后存储的23位有效数字的位置是在第128位开始的,我们把这个浮点数展开为256位,是这样表示的:
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
前面的那些零和后面的那些零都是“虚构的”,也就是说这些零并没有被存储在float里面,而是同于补充位数的。第127位被强制设置为“1”,这是float的规定。
浮点数存储了它的小数点位置:01111111,也就是“127”这里。那么我们最终得到的浮点数是:1.0

同样的,double也是和float一样用三个部分表示浮点数:有效数字,小数点位置,符号。
double的有效数字是52位,小数点位置用11个位表示,符号位用一个位表示。十进制可以精确到16个数位左右。
我这里举个例子:浮点数1.0是怎么存储的:
0 01111111111 0000000000000000000000000000000000000000000000000000(0x3FF0000000000000)
其中蓝色的部分是符号位,0表示正数。
黄色的部分表示小数点的位置,在从左往右数第1023位处。
绿色部分是有效数字,共52个0,也就是全零。
按照double浮点数的特性,第1023位的值必须是1,然后存储的52位有效数字的位置是在第1024位开始的,我们把这个浮点数展开为2048位,是这样表示的:
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
在这2048位的数字中,我们的double存储的52个有效数字在其中的绿色部分,也就是从1024位开始处。1023位被强制设置为1。可以看出,double的精度比起float提高了不少。
小数点的位置:01111111111表示小数点在第1023位的后面,因此最终得到的浮点数的数值是1.0

除了float和double,还有其它格式的浮点数:
Minifloat:迷你浮点数(8位):
1位符号位,4位小数点位置,3位有效数字。(PS.真够“迷你”的)
Half:半精度(16位):
1位符号位,5位小数点位置,10位有效数字。
x86 Extended Precision Format:x86扩展精度格式(80位):
1位符号位,15位小数点位置,1位特殊位,63位有效数字。特殊位请看http://en.wikipedia.org/wiki/Extended_precision
Quadruple:四倍精度(128位):
1位符号位,15位小数点位置,112位有效数字。

IEEE规定:
1、表示小数点位置的部分如果全零,那么这个浮点数的值为0,而如果这个时候有效数字部分非零,那么这个浮点数就“不是一个数”(NaN)
2、表示小数点位置的部分如果全一,那么这个浮点数的值为无穷大。
3、浮点数能表示的最大数值:表示小数点位置的部分除了最低位为零其它均为一,有效数字全为1
4、浮点数能表示的最小数值:表示小数点位置的部分除了最低位为一其它均为零,有效数字全为0

参考资料
http://en.wikipedia.org/wiki/Minifloat
http://en.wikipedia.org/wiki/Half-precision_floating-point_format
http://en.wikipedia.org/wiki/Sin ... oating-point_format
http://en.wikipedia.org/wiki/Dou ... oating-point_format
http://en.wikipedia.org/wiki/Extended_precision
http://en.wikipedia.org/wiki/Qua ... oating-point_format

https://www.0xaa55.com/forum.php?mod=viewthread&tid=462

时间: 2024-11-02 23:38:07

IEEE浮点数float、double的存储结构的相关文章

C/C++中float和double的存储结构

浮点数在内存中的存储格式  http://blog.csdn.net/happylife1527/article/details/8059219 http://blog.csdn.net/aa2010aa/article/details/4982375 http://www.cnblogs.com/rain-lei/p/3619173.html http://zhidao.baidu.com/link?url=g1wFWLfS7JrCSeic0HvTR9b5RRj1dleuEPjVTv1u7N4

float与 double型数据存储---IEEE浮点数表示法

目前C/C++编译器标准都遵照IEEE制定的浮点数表示法来进行float,double运算. 这种结构是一种科学计数法,用符号.指数和尾数来表示,底数定为2--即把一个浮点数表示为尾数乘以2的指数次方再添上符号.下面是具体的规格:               符号位     指数部分    尾数       长度float           1             8              23          32double       1            11      

Java 浮点数 float或double类型的表示范围和精度

隐约记得,浮点数判断大小好像有陷阱,因为底层的二进制数不能精确表示所有的小数.有时候会产生让人觉得莫名其妙的事情. 如在java中, 0.99999999f==1f //true 0.9f==1f //false 要明白这些,首先要搞清楚float和double在内存结构 1.内存结构 float和double的范围是由指数的位数来决定的. float的指数位有8位,而double的指数位有11位,分布如下: float: 1bit(符号位) 8bits(指数位) 23bits(尾数位) dou

Java浮点数float和double精确计算的精度误差问题总结

1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结果出现误差. 原因:超出float精度范围,无法精确计算. float和double的精度是由尾数的位数来决定的.浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响. float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字: double:2^5

C语言浮点数存储结构

float类型占四个字节,每个字节占8位,总共32位,其内存结构如下图: 31位为符号位:0表示正数,1表示负数 31~23位:共8位表示指数位,内存存储数据从0~2^8-1=255,由于指数可以是正也可以是负,所以指数位采用移位存储表示数据,8位有符号有可表示数据从-128~127,所以指数位表示的实际指数应该是无符号位数减去127,例如0000 0000表示为0-127=-127,1111 1111表示为255-127=128,1000 0001表示为129-127=2 22~0位:共23位

float,double等精度丢失问题 float,double内存表示

问题提出:12.0f-11.9f=0.10000038,"减不尽"为什么? 来自MSDN的解释: http://msdn.microsoft.com/zh-cn/c151dt3s.aspx 为何浮点数可能丢失精度浮点十进制值通常没有完全相同的二进制表示形式. 这是 CPU 所采用的浮点数据表示形式的副作用. 为此,可能会经历一些精度丢失,并且一些浮点运算可能会产生意外的结果. 导致此行为的原因是下面之一: 十进制数的二进制表示形式可能不精确. 使用的数字之间类型不匹配(例如,混合使用浮

浮点数float累加误差分析与解决

1.  浮点数IEEE 754表示方法 要搞清楚float累加为什么会产生误差,必须先大致理解float在机器里怎么存储的,具体的表示参考[1] 和 [2], 这里只介绍一下组成 由上图可知(摘在[2]), 浮点数由: 符号位 + 指数位 + 尾数部分, 三部分组成.由于机器中都是由二进制存储的,那么一个10进制的小数如何表示成二进制.例如: 8.25转成二进制为1000.01, 这是因为 1000.01 = 1*2^3 + 0*2^2 + 0*2^1 + 0*2^0 + 0*2^-1 + 2*

浮点数float累加误差解决方式总结

首先是float累加产生误差的原因,该部分转自:http://blog.csdn.net/zhrh0096/article/details/38589067 1.  浮点数IEEE 754表示方法 要搞清楚float累加为什么会产生误差,必须先大致理解float在机器里怎么存储的,具体的表示参考[1] 和 [2], 这里只介绍一下组成 由上图可知(摘在[2]), 浮点数由: 符号位 + 指数位 + 尾数部分, 三部分组成.由于机器中都是由二进制存储的,那么一个10进制的小数如何表示成二进制.例如

浮点数在计算机中存储方式

浮点数在计算机中存储方式 C语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范的, float遵从的是IEEE R32.24 ,而double 遵从的是R64.53. 无论是单精度还是双精度在存储中都分为三个