IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言中两种浮点数的范围、精度计算 -> 正文阅读

[C++知识库]C语言中两种浮点数的范围、精度计算

概述

C语言里面支持两种浮点数类型:float和double,其中在32位机器上,float是32bit的变量类型,而double是双字也就是64bit的。编程的时候,有时需要知道两种数据数据表示范围和表示精度,下面给出两种结果的求解过程。

浮点格式

精度和范围与数据的存储格式密切相关,所以我们先来看一看它们的存储格式:
对于float类型的变量,其底层的存储格式为:

符号位指数阶码尾数
1bit8bit23bit

对于double类型的变量,底层的存储格式为:

符号位指数阶码尾数
1bit11bit52bit

浮点数底层的格式告诉我们它是以科学计数法表示浮点数据的,我们用S表示1bit的符号位,F表示23bit或52bit的尾数域,E表示8bit或者11bit的指数域,那么其科学表示法的的形式为:

( ? 1 ) S ? F ? 2 E (-1)^S*F*2^E (?1)S?F?2E
为了尽可能地充分利用各个bit,根据科学计数法的格式,二进制的科学计数法小数点前是1时才是标准的写法,例如 0.101 ? 2 2 、 10.101 ? 2 2 0.101*2^2、10.101*2^2 0.101?2210.101?22就不是标准的计数方式, 1.01 ? 2 1 、 1.0101 ? 2 3 1.01*2^1、1.0101*2^3 1.01?211.0101?23就是标准的计数格式,所以可以省略小数点前的1,这样就可以用尽可能多的bit表示尾数域,从而提高浮点数的精度。

按照IEEE标准浮点格式的类型表示了所有的实数域,包括三个特殊的数:0和正负无穷大。我们以float类型的浮点数为例,当所有bit都为0的时候,表示0.0f,它的32bit为:0000 0000 0000 0000 0000 0000 0000 0000。它表示的真实值为: + 1.0 ? 2 ? 127 +1.0*2^{-127} +1.0?2?127(是一个很接近于0的正数,这个时候也可以看做正的无穷小;当然符号位也可以是1,这个时候表示的是负无穷小,也就是-0),指数部分之所以是-127而不是0,是因为IEEE标准规定指数部分减去127才是才是真正的指数值,这里面有两个问题,我们一一解答:第一,为什么要减一下?首先,指数域的8bit表示的是无符号的8bit,因为浮点数包含了无穷小的数,所以指数部分肯定有为负数的情况,那为什么不直接用有符号的8bit表示?是因为为了方便在符号位一样的条件下可以直接通过指数域比较浮点数的大小,如果是sign 类型那么-1就表示为0xff,看起来是很大的一个数,所以需要减一下,才有可能出现指数域为负数的情况。第二,为什么是127而不是128或者别的值?只有减去127的时候,才能保证无穷大时的情况和无穷小时的情况的指数符号相反,保持平衡。无穷大的时候就是指指数域和尾数域全部是1的情况,当符号位为1、0时就可以分别代表负的无穷大和正的无穷大(实际上只是一个理论的无穷大,还是有范围的,下面会讲)。

范围推导

我们先详细的计算一遍float类型的范围,然后double类型的直接给出结果。首先看它的最大的情况,此时S=0,F全部是0,指数域全部是1,此时32bit的值为:0111 1111 1000 0000 0000 0000 0000 0000。它的精确值为: + 1. 0 2 ? 2 255 ? 127 +1.0_2*2^{255-127} +1.02??2255?127,对应的十进制约为: + 1.0 ? 2 + 128 ≈ + 3.4 ? 1 0 38 +1.0*2^{+128} \approx{+3.4*10^{38}} +1.0?2+128+3.4?1038,负的无穷大就是当S=1的时候,即: ? 1.0 ? 2 + 128 ≈ ? 3.4 ? 1 0 38 -1.0*2^{+128} \approx{-3.4*10^{38}} ?1.0?2+128?3.4?1038,正无穷小时的实际值上面已经给出,这里不再赘述。另外在IEEE标准中将E全是1,F中非零表示NaN(Not a Number),它表示运算得到的结果不是一个数,比如1/0(除数为0)的结果就是NaN。

直接给出double类型的数表示的范围: ? 1.7 ? 1 0 + 308 ~ + 1.7 ? 1 0 + 308 -1.7*10^{+308} \sim +1.7*10^{+308} ?1.7?10+308+1.7?10+308

精度计算

精度是和尾数域直接相关的,所谓的单精度双精度,它们的其中一个差别就在与后者的尾数域所占的bit比前者多很多。

我们可以这样理解:精度的“颗粒”就是尾数域的最后一个bit每增加1,我们的实际值(十进制下)会增加多少?仍然以float类型为例,我们知道float变量的尾数域长度为23bit,也就是小数点后有23个二进制bit,那么每增加1,对应的十进制就增加了 2 ? 23 ≈ 0.00000011 9 10 2^{-23}\approx{0.000000119_{10}} 2?230.00000011910?。也就是说,float类型的精度在十进制里面小数点后6位一定时有效的,第七位可能有效。同理double类型的十进制下的精度为15~16位,第15位一定有效。

总结

类型有效位范围
float6~7 ? 3.4 ? 1 0 38 + 3.4 ? 1 0 38 -3.4*10^{38}+3.4*10^{38} ?3.4?1038+3.4?1038
double15~16 ? 1.7 ? 1 0 + 308 ~ + 1.7 ? 1 0 + 308 -1.7*10^{+308} \sim +1.7*10^{+308} ?1.7?10+308+1.7?10+308
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 16:54:12  更:2021-10-03 16:56:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:58:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码