浮点数的范围和精度问题(从原理到结论)

浮点数的范围和精度问题(float和double的比较)

今天遇到一道C++题,非常简单,就是比较两个浮点数是否相等。我的第一思路就是输入两个double类型的变量a,b,看a-b的绝对值是否小于 1 e − 8 1e^{-8} 1e8,是则相等。
  在这里插入图片描述
  但是!!!问题并没有到这里结束,我去瞄了一眼其他人的解法,发现居然可以输入float类型的变量,然后直接用逻辑判断==就可以了,然后在线测评也通过了,也是非常神奇。于是对float和double类型的范围和精度产生了兴趣,为啥误差精度为 1 e − 8 1e^{-8} 1e8时float类型的数就能直接判断,而double却不行呢?
  到网上搜罗到了一些解答,本文对其进行了归纳整理。

  1. 关于浮点数的精度与取值范围的问题
  2. float的范围和有效数字怎么算出来的?
  3. float与double的范围和精度
  4. float和double的精度
  5. 维基百科 IEEE 754标准(二进制浮点数算术标准)

这首先得从浮点数在计算机中的表示和存储方式说起。
  
   根据IEEE标准,浮点数是通过科学计数法来存储的,比如120.5用十进制的科学计数法来表示就是 1.205 × 1 0 2 1.205\times10^{2} 1.205×102,但是计算机中所有数据都是用二进制存储的,所以得先转换为二进制数,即 1.1110001 × 2 6 1.1110001\times2^{6} 1.1110001×26

在这里插入图片描述

浮点数在计算机中的存储分为三个部分:
   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能够表示的最大值为 3.40 × 1 0 38 3.40\times10^{38} 3.40×1038,最小区分精度约为 1.19 × 1 0 − 7 1.19\times10^{-7} 1.19×107(这一点和最开始那道题目有点矛盾,等我尝试几组数据之后再补充)。

在这里插入图片描述

double能够表示的最大值为 1.80 × 1 0 308 1.80\times10^{308} 1.80×10308,最小区分精度约为 2.22 × 1 0 − 16 2.22\times10^{-16} 2.22×1016

不过这宏定义的最大最小值感觉并不是我们所认为的“不溢出内存的情况下所能表示的最大数字”,我现在也说不清,留个问题之后慢慢琢磨好了。

浮点数的精度

这个解释起来轻松一点,精度这里指的是最大有效数字的位数,即只需要考虑尾数部分就可以啦。
  对于float类型,尾数部分是23,转换成10进制的精度, 2 23 = 1 0 x 2^{23}=10^x 223=10x --> x = 23 l o g 2 ≈ 6.92 x=23log2\approx6.92 x=23log26.92,所以23位2进制最多只能表示6位10进制数,这里就是头文件中FLT_DIG=6的来由。
  但还有一种说法,也是网上的主流说法,二进制小数点的第一位永远都是1,可以省略,实际上二进制的精度为24,所以10进制的精度为7。

  • 36
    点赞
  • 120
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maples丶丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值