1. 摘要

在了解到C语言中整型是以二进制补码形式存储在内存中后,我们不禁很好奇:那么浮点型的数据是以什么形式存储在内存中的呢?

实际上,早在1985年,电气电子工程师学会就制定了IEEE 754标准来解决单精度浮点数在计算机内存中的存储问题。

那么接下来,我们就以IEEE754-1985版来看一看浮点数在内存中的真实面目。

2. 浮点数的表达方式

2.1 浮点数的组成

浮点型家族中包含有:float、double、long double类型

IEEE 754标准下,一个浮点数V可以被拆解成三个部分

V = (-1) ^ S * f * 2 ^ E
  1. 1-bit sign S ------ 符号位S,用来表示正负
  2. Biased exponent e = E+bias:指数位,负责浮点数的大小
  3. Fraction f = · b1b2 … bp−1:小数位,负责浮点数的精度,且f大于等于1小于2

2.2 单精度浮点数

对于32位的单精度浮点数而言,内存中32个bit位是这样分配的:

  1. 1位符号位
  2. 8位指数位
  3. 23位小数位

2.3 双精度浮点数

对于64位的双精度浮点数而言,内存中64个bit位是这样分配的:

  1. 1位符号位
  2. 11位指数位
  3. 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 Numbersgeeksforgeeks

2.IEEE 754-1985Wikipedia

3.Single-precision floating-point formatWikipedia

4.IEEE Standard for Binary Floating-Point Arithmetic. 1985. doi:10.1109/IEEESTD.1985.82928. ISBN 0-7381-1165-1.

5.NaN,Wikipedia

注:来自维基百科参考文献的快照若有需要,请联系本人

感谢你们的阅读!本人水平有限,如有错误,还望指正!

【C语言】浮点型在内存中的存储的更多相关文章

  1. C语言中字符型,整数型,浮点型在内存中如何存储

    ···void main() { unsigned char a = 97; printf("%p",&a); printf("%c,%d\n", a, ...

  2. C语言代码在内存中的存储

    http://blog.chinaunix.net/uid-26430381-id-4359960.html

  3. C语言之数据在内存中的存储

    C语言之数据在内存中的存储 在我们学习此之前,我们先来回忆一下C语言中都有哪些数据类型呢? 首先我们来看看C语言中的基本的内置类型: char //字符数据类型 short //短整型 int //整 ...

  4. C语言中浮点数在内存中的存储方式

    关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4. ...

  5. 【C语言】整型在内存中的存储

    整型在内存中的存储 1.整型的归类 char short int long 以上都分为有符号(signed)与无符号(unsigned)的类型 2.原码.反码和补码 2.1 定义 计算机在表示一个数字 ...

  6. <转载>浅谈C/C++的浮点数在内存中的存储方式

    C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中 ...

  7. 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)

    https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...

  8. 一个 -100.01 的double 在内存中怎么存储的. 一个中文String 在内存中占多少直接 utf-8 / GBK

    一.-100.01 的double 在内存中怎么存储的 double双精度数据类型存储格式IEEE 双精度格式为8字节64位,由三个字段组成:52 位小数 f : 11 位偏置指数 e :以及 1 位 ...

  9. float 在内存中如何存储的

    float类型数字在计算机中用4个字节存储.遵循IEEE-754格式标准:    一个浮点数有2部分组成:底数m和指数e 底数部分 使用二进制数来表示此浮点数的实际值指数部分 占用8bit的二进制数, ...

随机推荐

  1. buu 简单注册器

    一.本身对安卓逆向这块不是很熟悉,为了看这题稍微了解了一下,原来安卓虚拟机解释运行的是dex文件,和java的字节码不一样,然后是smail语法,这块我不会,所以找个了个神器来反编译2333,然后这题 ...

  2. windows服务器下MySQL配置字符集

    这俩天公司使用.netcore微服务+mysql做项目,mysql在使用的时候总是出现一些字符集的问题,修改utf8或utf8mb4后mysql的服务就启动不了,这里做下记录如果把my.ini中的字符 ...

  3. Android 开发学习进程0.32 dwonloadmanager使用

    downloadmanager时Android系统下载器,使用系统下载器可以避免用stream流读入内存可能导致的内存溢出问题.以下为downloadmanager初始化部分.apkurl为下载网络路 ...

  4. 二、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之Modules的几种加载方式

    这一篇梳理Prism中07示例Module的几种加载方式. 07示例分为了5个,有5种不同的Module加载方式. 我们开始学习加载Modules 观察07-Modules-Appconfig示例 分 ...

  5. WIN10 网卡驱动异常代码56的问题及解决方法

    故障描述: 原来使用正常的一个微机室,突然一天控制端主机网络连接异常,平时的网络控制软件无法使用.检查网络配置正常,网络诊断.修复.将网卡禁用也没有效果:后来删除网卡想重装,则恶运开始,无法安装驱动: ...

  6. Swift-为什么String转换Int的结果是nil

    摘要 知其然,更要知其所以然.前段时间用 String 转换 Int 处理时,发现一种情况返回 nil,就换成 String 转换 Double 的方式处理.今天就要来看看这种返回 nil 的情况是怎 ...

  7. Java基础之反射总结

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...

  8. Python基础之魔术方法(一个序列容器的魔术方法)

    # 创建自己想要的序列容器魔术方法'''__len__():调用len(obj)函数会调用这个魔术方法__getitem__(self,key):在使用下标操作temp['key']以及切片操作的时候 ...

  9. PAT乙级:1094 谷歌的招聘 (20分)

    PAT乙级:1094 谷歌的招聘 (20分) 题干 2004 年 7 月,谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌(如下图)用于招聘.内容超级简单,就是一个以 .com 结尾的网址,而前面 ...

  10. POJ3048

    素数筛,数据范围不大,直接暴力筛. 坑:有个数据是 1 1,答案是1.差点没把我卡去世. 我的三观哪去了. #include<iostream> #include<cstdio> ...