通俗易懂的Float和Double结构解析
引入一下
首先,众所周知,float和double类型都是浮点型。
所以用float和double类型的数据都是浮点数。
所以,什么是浮点数?
浮点的点,我个人认为是小数点的意思
而“浮”,我认为是浮动,不稳定的意思,可以联想一下家里的肥皂泡,不稳定动来动去的
结合起来就是不稳定的小数点。
就是说这个数的小数点非常灵活,可以移动。
在数学上会有什么方法和小数点的移动关系非常紧密?
没错,它就是
科学计数法
科学计数法想必大家有一定的了解。
浮点数是采用科学计数法来表示的,小数点的位置是可以漂浮不定的,正因为小数点的移动以及科学技术法的参与,float和double才能表示小数,才能用于进行小数的运算。
当然,我以上说的太抽象了(没有例子讲个毛啊!),理解不了非常正常, 不着急,听我慢慢讲:
float类型
首先,它是4个字节,没错,和int类型一样的4个字节哦!
所以,用二进制表示时,一个float类型应该是这种格式,32个位
00000000 00000000 00000000 00000000
如果看过我上一篇写过的int类型解析,应该就会知道决定正负的符号位是什么东西。
float也是有正负的,所以也是有符号位的。
0|0000000 00000000 00000000 00000000 0为正 1为负
好。
那么为什么科学计数法会和float有关联?
如果查看比较权威的文档,你就会发现,float除了符号位,还有两个组成成分。
长8位的指数
长23位的尾数
1+8+23 = 32刚刚好。
而指数和尾数是科学计数法的重要组成成分。
看不懂?别慌,我慢慢说:
三个成分的组合如下:
0|00000000 |0000000 00000000 00000000
符号位 指数 尾数
什么是尾数?隐含位又是什么?
个人理解,尾数是float数去除小数点后的,干净的数
如float temp = 19.625
先把它转换为二进制,10011.101 (小数的二进制转换是基本功了,可以去了解一下)
然后用科学计数法把它表示为1.0011 101*2^4;<-二进制的科学计数法需要了解形式
然后把小数点和后面的指数部分剥离,得到了10011101,
它为正数,符号位为0.
在暂时不考虑指数的情况下,现在应该这个float浮点型的情况应该是这样:
0 - 00000000 - 0011101 0000000000000000 <-注意存储的方向,从左向右存,有点反直觉的哦!
啊?为什么是0011101?不是10011101吗?最前面那个1去哪里了???
好
如果你之前有了解过有关float的文档的话,想必一定听过“隐含位"这个概念。不理解也没关系,我来讲:
一个二进制数,只有0和1
排在1前面的0,我们一般省略掉,因为它对数值没什么影响。
如:
000011 = 11 = 3
那我们是不是可以推出来,如果二进制数把所有没有“价值”的,排在第一个1前的,”0“全部去掉,像上面这样,那第一位是不是一定是1?
如果肯定是1,那就默认它存在不就好了?
所以,为什么是0011101?不是10011101吗?最前面那个1去哪里了???
它不是消失了,它是省略了,隐含了,反正最前面都是1,干脆把第一个1省略就行了,反正电脑记得这个1,它会不会忘记算的。故称为“隐含位”。(请忽略0,那个是特殊情况)
这么麻烦,不省略不好吗?
但是这种方法可以让一个float表示更多的数,拥有更大的表示范围,所以就只能委屈一下人类了(笑)
那么,下一个问题
什么是指数?
数学的东西啊,就是那么要命。
这里的指数从用法到概念都比较特别,它用于表达小数的位置在哪。当然,我以上说的太抽象了(没有例子讲个毛啊!)
所以,我就直接说用法了。
指数位有8位,说明它可以表示0 - 2^8-1, 即 0 - 255
由于小数点不光可以左移让尾数变小还可以右移让尾数变大,所以从0开始记录就很不方便。
有一个很厉害很官方的协会叫IEEE定义了合适的方法来表示左移还是右移。
以0-255的中心127,即0111 1111为中心。
若小数点让尾数向左移4位,把指数置为127+4 = 131 = 1000 0011
若小数点让尾数向右移4位,把指数置为127-4 = 123 = 0111 1011
所以综上所述,
19.625 = 10011.101 = 用科学技术法把它表示为
1.0011 101*2^4;=
0 - 1000 0011 - 001 1101 0000 0000 0000 0000。
可以看出,化为二进制的1.0011 101*2^4,向右移四位就是10011.101,所以就是移动4位。
至此,float的结构完全解析了。
而double,作为8字节的浮点型,64位数
1位符号位,
11位指数
52位尾数,原理基本和float相同。
非常感谢您可以耐心读到这里,博客内容写的很粗糙,只是分享自己在学习中的一些想法,有错误指正和改进欢迎提出!