在计算机内存中,float型数据占4个字节,double型占8个字节,它们在计算机中的存储分为三个部分:
- 符号位:0代表正,1代表负。
- 指数位:将一个二进制数用科学计数法表示之后指数的值。
- 尾数位:用科学计数法表示的前面的数。
其中存储的方式如图
double型的数据存储方式与之类似,只不过能表示更大的数位
现在就用float型的数据来举例吧。
比如,12.5f为一个float型的浮点数,先把它转化为二进制数为1100.1,用科学计数法表示为1.1001*2^3。现在就可以表示把这个二进制数分为三部分
符号位,这个数为正数,所以符号位为0。
尾数位为1.1001,由于尾数的整数部分肯定为1,所以可以省略,在尾数部分只存储小数点后的数,即可以用23bit来表示24bit的精度,4个bit可以精确到小数点后一位,所以24bit就可以表示小数点后6位的数字啦。
指数位有点特别,需要先加上127(称为偏移量),然后再存到内存中。为什么需要加上这个偏移量呢,维基百科给出了关键的原因,“采用指数的实际值加上固定的偏移值的办法表示浮点数的指数,好处是可以用长度为e个比特的无符号整数来表示所有的指数取值,这使得两个浮点数的指数大小的比较更为容易。”这样做的目的就是为了之后的计算更加容易。所以在这个例子里面,指数位存的就是(127+3)的二进制数,即10000010。
所以现在就能将12.5f这个浮点数存到计算机中啦(不考虑反码和补码),表示出来为:0 10000010 10010000000000000000000
对于一些小数部分无法准确表示的数来说,比如3.3,这个数字的小数部分没办法表示为准确的二进制数,为11.010011001100110011......无限循环下去,这个时候,由于尾数部分只能存储23bit的数据,所以这个时候就会把多余的尾数舍弃掉(损失精度),然后存够23bit的数据。
对于浮点数的读取,只要按上面的步骤反着来一遍就好了:先取出尾数部分的数据,然后给整数部分补上1;接着取出指数位的数据,大于127小数点右移,移动位数为n-127;
最后从符号位取出数据判断符号,然后你就可以得到一个完整的数据了。当然这个数据是二级制格式的,如果想让大部分人都能看懂,还需要把它转换为十进制格式啦。