【C语言】浮点型在内存中的存储
1. 摘要
在了解到C语言中整型是以二进制补码形式存储在内存中后,我们不禁很好奇:那么浮点型的数据是以什么形式存储在内存中的呢?
实际上,早在1985年,电气电子工程师学会就制定了IEEE 754标准来解决单精度浮点数在计算机内存中的存储问题。
那么接下来,我们就以IEEE754-1985版来看一看浮点数在内存中的真实面目。
2. 浮点数的表达方式
2.1 浮点数的组成
浮点型家族中包含有:float、double、long double类型
IEEE 754标准下,一个浮点数V可以被拆解成三个部分
V = (-1) ^ S * f * 2 ^ E
- 1-bit sign S ------ 符号位S,用来表示正负
- Biased exponent e = E+bias:指数位,负责浮点数的大小
- Fraction f = · b1b2 … bp−1:小数位,负责浮点数的精度,且f大于等于1小于2
2.2 单精度浮点数
对于32位的单精度浮点数而言,内存中32个bit位是这样分配的:
- 1位符号位
- 8位指数位
- 23位小数位
2.3 双精度浮点数
对于64位的双精度浮点数而言,内存中64个bit位是这样分配的:
- 1位符号位
- 11位指数位
- 52位小数位
2.4 指数偏差(Biased Exponent)
2.4.1指数E不为全0或全1
对于float型,我们发现8位的E如果就表示8个无符号的二进制位,那么指数位2^E只能表示比1大的数,而不能表示0-1之间的数,这就导致负指数没法被表示出来。
为了表示负指数,规定E在内存中的值等于你想要真实表达的指数的值再加上中间数127(对于double型,这个中间数是1023),所以即使你想使用负指数,加上127后E也还是非负的。
这就叫“指数偏差”。
2.4.2 指数位E全为1
1)小数位 f 不全为0
无论符号位s是什么,浮点数V代表NaN
NaN 是 Not a number 的意思,代表了一个无法被表示出来的值,比如一个数除以0或负数的平方根
2)小数位 f 全为0
浮点数
V = ( −1)s∞
,此时表示正负无穷大
2.4.3 指数位E全为0
以下用单精度浮点数为例:
1)小数位 f 不全为0
V = (−1)s * 2−126 * (0.f)
2)小数位 f 全为0
V = (−1)s * 0 ,此时V表示正负0
2.5 小数位的规定(fraction)
小数位 f 是一个 [1,2) 间的数,所以 f 可以写成以上图片中的形式:1.xxxxx
由于 f 的第一位总是1,所以我们将第一位的1省略,这样就能多表示一位小数点之后的数了
2.6 浮点数的范围
浮点数的所能表达的最大值/最小值被定义在了头文件<float.h>中
对于float型:
最小:2-126= 1.175×10-38
最大:2128 = 3.403×1038
对于double型:
最小:2-1022= 2.225×10-308
最大:21024 = 1.798×10308
3. 代码分析
让我们来看一段代码来进行具体分析
#include<stdio.h>
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
那么运行结果是什么呢?
不急,我们先对代码进行一波分析。
第一步
我们创建了一个int型变量n并赋值为9
第二步
我们将一个float型的指针变量pfloat指向了n
那我们就要问了:整型9在内存中是怎么存储的呢?
当然是以补码形式存储,所以这内存中的32个比特位是:
00000000 00000000 00000000 00001001
第三步
我们以%d(有符号整型)形式对上述32个比特位进行打印,显然屏幕上应输出:
n的值为:9
第四步
我们以%f(float型)形式对上述32个比特位进行打印
再看这32个比特位
00000000 00000000 00000000 00001001
我们重拾这个公式:V = (-1) ^ S * f * 2 ^ E 与 这张图:
重新将上述32个比特位排序
0 00000000 00000000000000000001001
故 V = (−1)s * 2−126 * (0.00000000000000000001001)2,是一个很小很小的数,所以屏幕上默认打印小数点后六位的话,应输出:
*pFloat的值为:0.000000
第五步
将pfloat指向地址的内容修改为9.0,显然此时上述32个比特位中存储的是单精度浮点数的二进制表达方式,遵循IEEE 754标准
(9.0)10 = (1001.0)2 = (1.0010 * 23)2
所以上述32个比特位此时应该是:
0 10000010 00100000000000000000000
第六步
我们以%d(有符号整型)形式对上述32个比特位进行打印,显然屏幕上应输出:
num的值为:1,091,567,616
第七步
我们以%f(float型)形式对上述32个比特位进行打印,显然屏幕上应输出:
*pFloat的值为:9.000000
运行截图如下:
4.参考文献
1.IEEE Standard 754 Floating Point Numbers,geeksforgeeks
2.IEEE 754-1985,Wikipedia
3.Single-precision floating-point format,Wikipedia
4.IEEE Standard for Binary Floating-Point Arithmetic. 1985. doi:10.1109/IEEESTD.1985.82928. ISBN 0-7381-1165-1.
5.NaN,Wikipedia
注:来自维基百科参考文献的快照若有需要,请联系本人
感谢你们的阅读!本人水平有限,如有错误,还望指正!
【C语言】浮点型在内存中的存储的更多相关文章
- C语言中字符型,整数型,浮点型在内存中如何存储
···void main() { unsigned char a = 97; printf("%p",&a); printf("%c,%d\n", a, ...
- C语言代码在内存中的存储
http://blog.chinaunix.net/uid-26430381-id-4359960.html
- C语言之数据在内存中的存储
C语言之数据在内存中的存储 在我们学习此之前,我们先来回忆一下C语言中都有哪些数据类型呢? 首先我们来看看C语言中的基本的内置类型: char //字符数据类型 short //短整型 int //整 ...
- C语言中浮点数在内存中的存储方式
关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4. ...
- 【C语言】整型在内存中的存储
整型在内存中的存储 1.整型的归类 char short int long 以上都分为有符号(signed)与无符号(unsigned)的类型 2.原码.反码和补码 2.1 定义 计算机在表示一个数字 ...
- <转载>浅谈C/C++的浮点数在内存中的存储方式
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中 ...
- 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)
https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...
- 一个 -100.01 的double 在内存中怎么存储的. 一个中文String 在内存中占多少直接 utf-8 / GBK
一.-100.01 的double 在内存中怎么存储的 double双精度数据类型存储格式IEEE 双精度格式为8字节64位,由三个字段组成:52 位小数 f : 11 位偏置指数 e :以及 1 位 ...
- float 在内存中如何存储的
float类型数字在计算机中用4个字节存储.遵循IEEE-754格式标准: 一个浮点数有2部分组成:底数m和指数e 底数部分 使用二进制数来表示此浮点数的实际值指数部分 占用8bit的二进制数, ...
随机推荐
- mysql导入脚本
#登陆 mysql -u root -p #创建数据库 CREATE DATABASE `gps` CHARACTER SET utf8 COLLATE utf8_general_ci; #选择数据库 ...
- Kotlin Coroutine(协程): 一、样例
@ 目录 前言 一.直接上例子 1.延时任务. 2.异步任务 3.并行任务: 4.定时任务: 总结 前言 你还在用 Hanlder + Message? 或者 AsyncTask? 你还在用 Rxja ...
- 通过MMIO的方式实现VIRTIO-BLK设备(一)
背景知识 什么是VIRTIO 使用完全虚拟化,Guest不加任何修改就可以运行在任何VMM上,VMM对于Guest是完全透明的.但每次I/O都将导致CPU在Guest模式与Host模式间切换,在I/O ...
- 『心善渊』Selenium3.0基础 — 27、unittest跳过测试的使用
目录 1.什么是跳过测试 2.常用的跳过测试方法和装饰器 3.跳过测试示例 4.TestCase.skipTest()方法 1.什么是跳过测试 当测试用例写完后,有些模块有改动时候,会影响到部分用例的 ...
- python使用笔记006-函数+json操作
一.函数 函数:提高代码的复用性 1.1 函数的定义 1 def hello(): 2 print('hello') 3 print('fdsfjslkfs') 4 5 #函数不调用就不会执行 6 h ...
- Kubernetes部署-二进制方式
环境配置 一.系统环境 序号 用途 系统 Docker版本 IP地址 1 Master CentOS Linux release 7.6.1810 (Core) 19.03.4 192.168.0.1 ...
- etcd学习(3)-grpc使用etcd做服务发现
grpc通过etcd实现服务发现 前言 服务注册 服务发现 负载均衡 集中式LB(Proxy Model) 进程内LB(Balancing-aware Client) 独立 LB 进程(Externa ...
- Jupyter notebook总是卡在int[*]怎么解决?
Jupyter notebook总是卡在int[*]怎么解决? 先看看后台的日志是怎么回事 运行Jupyter notebook会有一个命令行在运行,可以看看出现在error附近的的句子的意思再具体搜 ...
- java对接c++发布的webservice接口,其中参数类型有base64Binary格式(无需将图片数据转化为c++中的结构体)
接口名称: std::string SendVehiclePass(std::string VehiclePassInfo, struct xsd__base64Binary PlatePicData ...
- Skywalking-03:Skywalking本地调试
live-demo 与 skywalking 源码联调 构建项目 找一个目录执行如下命令 git clone https://github.com/apache/skywalking.git # cl ...