浮点数的范围和精度问题(float和double的比较)
今天遇到一道C++题,非常简单,就是比较两个浮点数是否相等。我的第一思路就是输入两个double类型的变量a,b
,看a-b
的绝对值是否小于
但是!!!问题并没有到这里结束,我去瞄了一眼其他人的解法,发现居然可以输入float类型的变量,然后直接用逻辑判断==
就可以了,然后在线测评也通过了,也是非常神奇。于是对float和double类型的范围和精度产生了兴趣,为啥误差精度为
到网上搜罗到了一些解答,本文对其进行了归纳整理。
这首先得从浮点数在计算机中的表示和存储方式说起。
根据IEEE标准,浮点数是通过科学计数法来存储的,比如120.5用十进制的科学计数法来表示就是
浮点数在计算机中的存储分为三个部分:
1. 符号位(sign):float和double符号位均为1位,0代表正数,1代表负数
2. 指数位(exponent):存储科学计数法中的指数部分,采用移位存储
3. 尾数位(fraction):存储科学计数法中的尾数部分
根据IEEE 754标准,单精度float类型使用32比特存储,其中1位表示符号,8位表示指数,23位表示尾数;双精度double类型使用64比特存储,1位符号位,11位指数位,52位尾数位。
然后再来讲讲移位存储。拿float来举例,内存中使用32位来存储float浮点数,其中第1位表示浮点数正负,第2~9位表示指数,后23位表示指数。表示指数的8位二进制虽然连续,但并不在同一字节中(实际上是由第一字节的后7位和第二字节的第1位组成),然后这8位指数位的第1位也是用来表示正负……然后我就没怎么弄懂了,欢迎大家赐教。总之如果按照移位存储,指数值最后需要加上偏移值127就对了。
浮点数的范围
后来发现在头文件float.h里其实已经解释的很清楚了(所以说没事多翻翻源码总是没错的):
float能够表示的最大值为
float能够表示的最大值为
不过这宏定义的最大最小值感觉并不是我们所认为的“不溢出内存的情况下所能表示的最大数字”,我现在也说不清,留个问题之后慢慢琢磨好了。
浮点数的精度
这个解释起来轻松一点,精度这里指的是最大有效数字的位数,即只需要考虑尾数部分就可以啦。
对于float类型,尾数部分是23,转换成10进制的精度,
FLT_DIG=6
的来由。
但还有一种说法,也是网上的主流说法,二进制小数点的第一位永远都是1,可以省略,实际上二进制的精度为24,所以10进制的精度为7。