众所周知,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,也就是全零。若是转换为十进制,大约就是六、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规定:
一、表示小数点位置的部分若是全零,那么这个浮点数的值为0,而若是这个时候有效数字部分非零,那么这个浮点数就“不是一个数”(NaN)
二、表示小数点位置的部分若是全一,那么这个浮点数的值为无穷大。
三、浮点数能表示的最大数值:表示小数点位置的部分除了最低位为零其它均为一,有效数字全为1
四、浮点数能表示的最小数值:表示小数点位置的部分除了最低位为一其它均为零,有效数字全为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_formatphp
https://www.0xaa55.com/forum.php?mod=viewthread&tid=462spa