浮点数在内存中的存储方式

浮点数保存的字节格式如下:

地址        +0          +1           +2           +3
内容    SEEE EEEE   EMMM MMMM    MMMM MMMM    MMMM MMMM

这里
S 代表符号位,1是负,0是正
E 偏移127的幂,二进制阶码=(EEEEEEEE)-127。
M 24位的尾数保存在23位中,只存储23位,最高位固定为1。此方法用最较少的位数实现了
较高的有效位数,提高了精度。

零是一个特定值,幂是0 尾数也是0。

浮点数-12.5作为一个十六进制数0xC1480000保存在存储区中,这个值如下:
地址 +0     +1     +2     +3
内容0xC1   0x48   0x00   0x00

浮点数和十六进制等效保存值之间的转换相当简单。下面的例子说明上面的值-12.5如何转
换。
浮点保存值不是一个直接的格式,要转换为一个浮点数,位必须按上面的浮点数保存格式表
所列的那样分开,例如:

地址       +0           +1            +2            +3
格式   SEEE EEEE    EMMM MMMM     MMMM MMMM     MMMM MMMM
二进制  11000001     01001000      00000000      00000000
十六进制   C1           48            00            00

从这个例子可以得到下面的信息:
  符号位是1 表示一个负数
  幂是二进制10000010或十进制130,130减去127是3,就是实际的幂。
  尾数是后面的二进制数10010000000000000000000


在尾数的左边有一个省略的小数点和1,这个1在浮点数的保存中经常省略,加上一个1和小数
点到尾数的开头,得到尾数值如下:
1.10010000000000000000000

接着,根据指数调整尾数.一个负的指数向左移动小数点.一个正的指数向右移动小数点.因为
指数是3,尾数调整如下:
1100.10000000000000000000

结果是一个二进制浮点数,小数点左边的二进制数代表所处位置的2的幂,例如:1100表示
(1*2^3)+(1*2^2)+(0*2^1)+(0*2^0)=12。
小数点的右边也代表所处位置的2的幂,只是幂是负的。例如:.100...表示(1*2^(-1))+
(0*2^(-2))+(0*2^(-2))...=0.5。
这些值的和是12.5。因为设置的符号位表示这数是负的,因此十六进制值0xC1480000表示-
12.5。

下面给个例子

#include <stdio.h>
union FloatData
{
    float f;
    unsigned char h[4];
};
void main(void)
{
    FloatData t;
    float temp = 0;
    printf("请输入一个数,输入100表示结束:");
    scanf("%f",&temp);
    t.f = temp;
   printf("%f在内存中的存放为:%2x %2x %2x %2x/n",t.f,t.h[0],t.h[1],t.h[2],t.h[3]);

}
 
 
 
 
 
关于多字节数据类型在内存中的存储问题


int ,short 分别是4、2字节。他们在内存中的存储方式下面举个例子说明。

int data = 0xf4f3f2f1;
其中低位存放在编址小的内存单元,高位存放在编址高的内存单元
如下:
地址:0x8000      0x8001    0x8002   0x8003
数据:   f1              f2            f3          f4
根据IEEE在1985年制定的标准来处理浮点数
单精度浮点数用4字节,包括1位符号位s(整数为0,负数为1),8位指数位e,23位有效位f
浮点型使用的是科学计数法,比如十进制的12345可以表示为1.2345 * 10^4(表示10的4次幂)
用二进制表示为 1.1000000111001 * 2^13
所以计算机中用浮点数表示12345这个十进制应该是这样的,s位为0,因为是正数,指数位为13+127=140(127为单精度浮点数偏移值,为了表示只有小数部分的数),有效位为1000000111001
计算的时候用 (-1)^s * 1.f * 2^(e-127) ,结果就是 1* 1.1000000111001 * 2^(140-127=13) ,和我们刚才表示的一样
还比如,十进制小数0.125转换为二进制小数0.001可以表示为 1* 1.0 * 2^(124-127=-3)
double,双精度浮点数有1位符号位、11位指数位和52位有效数
谢谢,和我找的资料差不多:)
知道公式
n=(-1)^s*m*2^e
e=|E|-bias
bias = 2^(k-1)-1(k为E的位数)
m=|1.M|


知道12345在内存中的10进制表示以后
0x4640e400 = 0(100 0110 0)<100 0000 1110 0100 0000>
括号中的数字为|E| = 140 所以e=140-127=13
尖括号中的数字为m=|1.M|=|1.100000011100100|=1.506958008
ok,
代入公式n = (-1)^0*1.506958008*2^13=12345
完工!!


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/djsl6071/archive/2007/03/16/1531336.aspx

<think>好的,我现在需要帮助用户了解C语言中浮点数内存中的存储方式,特别是IEEE 754标准。用户之前的问题是关于打印内存地址的,现在转向浮点数存储,这需要我结合之前的回答和提供的引用来组织信息。 首先,用户引用了三篇关于浮点数存储的文章,其中提到了IEEE 754标准、内存分配、符号位、阶码和尾数等内容。我需要将这些信息整合成一个清晰的解释。 我应该从基本结构开始,说明浮点数内存中分为符号位、阶码和尾数三个部分。根据引用,符号位占1位,阶码在float中是8位,double是11位,尾数则是23位或52位。需要解释每个部分的作用,比如符号位决定正负,阶码用偏移值表示指数,尾数存储规格化后的有效数字。 接下来,要详细说明规格化数的处理,包括隐含的前导1,以及阶码的偏移计算。比如float的偏移是127,所以存储的阶码e是实际指数E加127。这里需要引用用户提供的资料,如引用2和3中提到阶码的存储方式。 然后是非规格化数的情况,当阶码全为0时,尾数不再有隐含的1,这样可以表示接近0的小数。这点在引用1和2中都有涉及,需要说明为什么需要非规格化数,以及它们的作用。 特殊值部分,比如无穷大和NaN,当阶码全为1时的情况,这也需要提到,用户可能在应用中会遇到这些情况,引用1和3中有相关描述。 还需要举一个例子,比如12.5的存储方式,这样用户能更直观地理解转换过程。根据引用3中的例子,12.5转换为二进制是1100.1,规格化后是1.1001*2^3,所以符号位0,阶码3+127=130,尾数存储1001...,这样具体步骤能帮助用户理解。 最后,总结IEEE 754的关键点,并生成相关问题,确保用户能进一步探索。可能的问题包括规格化与非规格化的区别,阶码偏移的原因,以及特殊值的处理,这些都在引用中有涉及,需要自然地引出。 检查是否有遗漏的部分,比如内存对齐或者不同数据类型的差异,但根据用户提供的引用,主要关注float和double的结构。确保语言清晰,使用中文,避免术语混淆,并正确应用LaTeX格式,如阶码的偏移公式用$e = E + 127$表示。 现在需要将这些思考整理成结构化的回答,确保各部分逻辑连贯,引用正确的来源,并在末尾添加相关问题,帮助用户深入学习。</think>在C语言中,浮点数内存存储遵循$IEEE\ 754$标准[^1][^2][^3],具体分为以下核心部分: --- ### 一、存储结构(以`float`为例) 1. **符号位(Sign)** - 占1位,`0`表示正数,`1`表示负数[^1][^2] $$ \text{符号位} = \begin{cases} 0, & \text{正数} \\ 1, & \text{负数} \end{cases} $$ 2. **阶码(Exponent)** - 占8位(float)或11位(double),存储时需**加偏移值**转为无符号整数[^2][^3] - 偏移值计算:$2^{n-1}-1$($n$为阶码位数) - float偏移值$=127$,阶码范围$E \in [-126, +127]$ - 存储阶码$e = E + 127$ $$ \text{实际指数} = e_{\text{存储}} - \text{偏移值} $$ 3. **尾数(Significand/Mantissa)** - 占23位(float)或52位(double),存储**规格化后的二进制小数** - 隐含前导`1`(规格化数)或`0`(非规格化数)[^2][^3] $$ \text{实际尾数} = 1.\text{存储尾数} \quad (\text{规格化数}) $$ --- ### 二、规格化与非规格化 1. **规格化数(Normalized)** - 阶码不全为`0`且不全为`1` - 隐含前导`1`,例如二进制数$1.1001 \times 2^3$存储时仅保留`.1001$[^2] 2. **非规格化数(Denormalized)** - 阶码全为`0`,用于表示接近零的小数 - 隐含前导`0`,避免数值“下溢”问题[^3] 3. **特殊值** - 阶码全为`1`时: - 尾数全`0` → 无穷大($\pm \infty$) - 尾数非`0` → NaN(非数值)[^1] --- ### 三、示例分析(以`12.5`为例) 1. **十进制转二进制** $$ 12.5 = 1100.1_2 = 1.1001_2 \times 2^3 $$ 2. **内存存储** - 符号位:`0` - 阶码:$E=3 \Rightarrow e=3+127=130 \Rightarrow 10000010_2$ - 尾数:`.1001`后补零至23位 → `1001000...000` ```c // 内存布局(十六进制表示): // 符号位 | 阶码 | 尾数 // 0 | 10000010 | 1001000...000 → 0x41480000 ``` --- ### 四、IEEE 754关键特性总结 | 特性 | 说明 | |-----------------|----------------------------------------------------------------------| | **动态范围** | 通过阶码偏移扩展指数范围,如float实际指数范围$-126$至$+127$[^3] | | **精度控制** | 尾数隐含前导位节省存储空间,提升精度[^2] | | **特殊值兼容性**| 支持无穷大、NaN等特殊值,增强计算鲁棒性[^1] | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值