浮点数的表示
浮点数编码转换采用的是IEEE规定的编码标准,float 和 double 这2种数据类型转换原理相同,但由于表示的范围不一样,编码方式也有些许区别。
IEEE规定的浮点数编码会将一个浮点数转换为二进制数,以科学记数法划分:
image.png
对于一个32位单精度浮点数,数符分配1位,阶码分配8位,尾数分配23位,有效数字为 6-7 ,数值范围为 -3.4E+38~3.4E+38
对于一个64位双精度浮点数,数符分配1位,阶码分配11位,尾数分配52位,有效数字为 15-16 ,数值范围为 -1.7E-308~1.7E+308
例如 178.125
整数部分除2取余表示:10110010
小数乘2取整部分表示:001
合起来:10110010.001
转换成二进制浮点数,把小数点移动到整数位只有1,即为:1.0110010001 * 2 ^ 111,这里的111是二进制表示,表示阶数
现在基本上可以确定上面 S,E,M的值了:
数符:正数为0,负数为1
阶码:阶码计算公式:阶数 + 偏移量,阶码是需要作移码运算,在转换出来的二进制数里,阶数是111(十进制为7),对于单精度的浮点数,偏移值为 01111111 = 127(偏移量的计算是:2^(e-1)-1, e为阶码的位数),即:111+01111111 = 10000110
尾数:小数点后面的数,即 0110010001
image.png
int main()
{
float a = 178.125
}
(gdb) x/4tb &a
0x7fffffffe3ac: 00000000 00100000 00110010 01000011 // 低字节到高字节
浮点数的比较
判断两个浮点数变量是否相等,不能简单地通过 "==" 运算符实现,浮点数进行比较时,一般比较他们之间的差值在一定范围之内:。
关于浮点数和定点数
在计算机中处理小数点位置有浮点和定点两种,定点就是小数点永远在固定的位置上,比如说我们约定一种32位无符号定点数,它的小数点永远在第5位后面,这样最大能表示的数就是11111.111111111111111111111111111,它是32 - 2^-27,最小非零数是2^-27。
定点数是提前对齐好的小数,整数是一种特殊情况,小数点永远在最后一位之后。定点数的优点是很简单,大部分运算实现起来和整数一样或者略有变化,但是缺点则是表示范围,比如我们刚才的例子中,最大只能表示32;而且在表示很小的数的时候,大部分位都是0,精度很差,不能充分运用存储单元。
浮点数就是设计来克服这个缺点的,它相当于一个定点数加上一个阶码,阶码表示将这个定点数的小数点移动若干位。由于可以用阶码移动小数点,因此称为浮点数。
参考资料
1、https://zhuanlan.zhihu.com/p/144697348
2、https://www.zhihu.com/question/19848808/answer/120393769
