C++浮点数在内存中的存储详解

目录
  • 前言:
  • 浮点数的表示形式
  • 浮点数存储模型
  • 有效数字M
  • 指数E
  • 例题讲解
  • 总结

前言:

我们在码代码的时候,经常遇到过以整数形式存入,浮点数形式输出;或者浮点数形式存入整数形式输出。输出的结果往往让人意想不到,那么,为什么会发生这样的变化,又是什么导致发生变化,接下来,就让我们从存储内部结构出发,带你深度解刨!

我们以一个例子来说明一切

#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("n的值为:%d\n",n);
    printf("*pFloat的值为:%f\n",*pFloat);
    return 0;
}

这个例子我们将n以整数形式输入,再定义一个指针变量来存n的地址,,分别将n以整数、浮点数形式输出。

输出结果如下

n和*pFloat在内存中明明是同一个数,为什么浮点数和整数的解读结果会差别那么大?

要理解这个结果,一定要搞懂浮点数在计算机内部的表示方法。

浮点数的表示形式

根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式

(-1)^S*M*2^E(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。M表示有效数字,大于等于1,小于2.2^E表示指数位。

举例来说:

十进制的5.0,写成二进制是101.0,用科学计数法就是:1.01*2^2(类比于十进制的科学计数法:20000=2*10^4);

由于5.0是正数,所以S=0,根据上面,M=1.01,E=2。

所以,写成浮点数就是:(-1)^0*1.01*2^2。

浮点数存储模型

IEEE754规定:

对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

对于64位的浮点数,最高的1位是符号位s,接着的11位是指数E,剩下的52位为有效数字M。

有效数字M

前面我们给了M的范围是1≤M<2,那么为什么范围是这么多?我们知道,二进制最高位为1,用科学计数法表示以后,M的形式为1.xxxxx的形式,其中xxxxx表示小数部分。

IEEE754规定,在计算机内部保存M是,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

指数E

至于指数E,情况就比较复杂。

首先,E为一个无符号整型(unsingde int)

这意味着,如果E为8位,它的取值范围为0~255;如果E是11位,它的取值范围为0~204。但是我们知道,科学计数法中的E是可以出现负数的,所以IEEE754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于1位的E,这个中间数是1023。

比如:2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即化为二进制为10001001。

对于指数E从内存中取出还可以再分成三种情况:

(1) E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

比如:

0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即小数点右移1位,则为1.0*2^(-1),其阶码为-1+127=126,表示为01111110而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进制表示形式为:

0  01111110  00000000000000000000000

(2)E全为0

这时,浮点数的指数E等于1-127(或者1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

(3)E全为1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位S);

例题讲解

(1)printf("n的值为:%d\n",n);

n是以整数存入的,在内存中的存储为:

输出是整数,所以 输出的还是9。

(2)printf("*pFloat的值为:%f\n",*pFloat);

*pFloat相当于n的值,但输出却是以浮点数的形式输出,但存入还是以整数形式存入,这是,内存就会把存入的0 00000000 00000000000000000001001以浮点数形式处理,这里相当于,第一位就是S,即S=0,E全为0,剩下的为M,即M=00000000000000000001001。

(3)printf("n的值为:%d\n",n);

此时,*pFloat=9.0,也就是将9.0以浮点数形式存入,以整数形式取出。

根据前面,我们写出9.0的存储:

由于是正数,所以S=0;

9转换为二进制为1001,科学计数法:1.001*2^3;

∴E=3(属于第一种,既不是全0,也不是全1),存入时要加上127,则E的真实值为:E=3+127=130,化为二进制1000 0010

M后面补0补全23位,即:001  0000 0000 0000 0000

所以浮点数在内存中的存储为:

最后输出以整数形式输出,即把0 100000010 00100000000000000000000视为要输出的数的补码,但输出的是原码,因为最高位为0,所以这个数是正数,原反补相同,则输出这个数,化为十进制就是:

(4)printf("*pFloat的值为:%f\n",*pFloat);

以浮点数形式存入,以浮点数形式输出,最后输出还是9.000000,保留6位小数。

总结

到此这篇关于C++浮点数在内存中的存储详解的文章就介绍到这了,更多相关C++ 浮点数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C/C++的浮点数在内存中的存储方式分析及实例

    C/C++的浮点数在内存中的存储方式分析 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中,存放方式为  10000100(低地址单元) 00000100(高地址单元),因为Intel CPU的架构是小端模式.但是对于浮点数在内存是如何存储的?目前所有的C/C++编译器都是采用IEEE所制定的标准浮点格式,即二进制科学表示法. 在二进制科学表示法中,S=M*2^N 主要由三部分构成

  • 深入C/C++浮点数在内存中的存储方式详解

    任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中,存放方式为  10000100(低地址单元) 00000100(高地址单元),因为Intel CPU的架构是小端模式.但是对于浮点数在内存是如何存储的?目前所有的C/C++编译器都是采用IEEE所制定的标准浮点格式,即二进制科学表示法.在二进制科学表示法中,S=M*2^N 主要由三部分构成:符号位+阶码(N)+尾数(M).对于flo

  • C++浮点数在内存中的存储详解

    目录 前言: 浮点数的表示形式 浮点数存储模型 有效数字M 指数E 例题讲解 总结 前言: 我们在码代码的时候,经常遇到过以整数形式存入,浮点数形式输出:或者浮点数形式存入整数形式输出.输出的结果往往让人意想不到,那么,为什么会发生这样的变化,又是什么导致发生变化,接下来,就让我们从存储内部结构出发,带你深度解刨! 我们以一个例子来说明一切 #include<stdio.h> int main() { int n = 9; float *pFloat = (float *)&n; pr

  • C语言编程数据在内存中的存储详解

    目录 变量在计算机中有三种表示方式,原码反码,补码 原码 反码 补码 总结一下 浮点数在内存的储存 C语言中,有几种基本内置类型. int unsigned int signed int char unsigned char signed char long unsigned long signed long float double 在内存中创建变量,会在内存中开辟空间,并为其赋值. int a=10; 在计算机中,所有数据都是以二进制的形式存储在内存中. 变量在计算机中有三种表示方式,原码反

  • C++中整形与浮点型如何在内存中的存储详解

    目录 1 数据类型 1.1 类型的基本归类 2 整形在内存中的存储 2.1 二进制的三种形式 2.2 大小端字的介绍 3 浮点数在内存中的存储 3.1 浮点数存储规则 1 数据类型 前面我们已经知道了基本的内置类型: 类型的意义: 1. 使用这个类型开辟内存空间的大小(大小决定了使用范围). 2. 如何看待内存空间的视角. 1.1 类型的基本归类 整形家族: char unsigned char signed char short unsigned short [int] signed shor

  • 关于C语言中数据在内存中的存储详解

    前言 1. 数据类型详细介绍 2. 整形在内存中的存储:原码.反码.补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析 一.数据类型介绍 1.类型的基本归类 1.整形家族 char unsigned char signed char short unsigned short [int] signed short [int] int unsigned int signed int long unsigned long [int] signed long [int] 2.浮点型家族

  • C语言数据在内存中的存储详解

    目录 文章摘要 一.C语言的数据类型 数据类型基本分为: 二.隐式类型转换 1.什么是隐式类型转换 2.整型提升 3.类型转换 三.机器大小端 1.什么是大小端 2.大小端在截断的应用 3.判断当前机器的字节序是大端还是小端 四.整型在内存中的存储 1.原码.反码.补码 2.举例实践整型数据在内存的存储 总结 文章摘要 本文通过内存底层原理,帮你透彻了解数据存储进内存与从内存中读取的区别以及不同数据类型下数据计算.赋值的变化情况 要透彻理解这些,必须知道隐式类型转换以及机器大小端的概念,本文会对

  • Android中的存储详解

    目录 1.存储在App内部 2.SD卡外部存储 3.SharedPreferences存储 4.使用SQLite数据库存储 4.1 自己完成一个BaseDao类 4.2 使用Google写的API处理 4.3 事务使用 总结 1.存储在App内部 最简单的一种.在尝试过程中发现,手机中很多文件夹都没有权限读写.我们可以将我们需要写的文件存放到App中的files文件夹中,当然我们有权限在整个App中读写文件 可以通过API获取一个file对象,这里的this就是MainActivity类 //

  • PHP INT类型在内存中占字节详解

    本教程将介绍输出INT类型在内存中占多少个字节 新建一个333.php,如图所示: 添加php的界定符(<?php?>),如图所示: 声明PHP与浏览器交互的文件类型和编码,如图所示: 使用常量 PHP_INT_SIZE 来获取INT类型在内存中占多少个字节,如图所示: 使用 echo 语句输出常量 PHP_INT_SIZE 获取到的字节数,如图所示: 运行网页,在浏览器上显示获取到的结果,如图所示: section id="smaller-text-left-7">

  • C语言详细分析不同类型数据在内存中的存储

    目录 数据类型的介绍 类型的基本归类 整形在内存中的存储 大小端介绍 一道笔试题 浮点数在内存中的存储 浮点数存储规则 剖析题目 数据类型的介绍 在我们之前的学习当中我们已经介绍了基本的内置类型 char 字符数据类型 short 短整型 int 整形 long 长整型 long long 更长的整形 float 单精度浮点数 double 双精度浮点数 这些类型的意义是: 1.使用这个类型开辟内存空间的大小,大小决定了使用范围 2.如何看待内存空间的视角. 类型的基本归类 整形 整形中分为有符

随机推荐