C语言中整数和浮点数是如何在内存中存储

本文详细解释了整数(包括有符号和无符号)的补码存储方式,以及浮点数(如float和double)的二进制表示方法,涉及IEEE754标准,包括符号位、指数位和有效数字的存储策略。通过实例展示了整数和浮点数在内存中的实际存储情况。
摘要由CSDN通过智能技术生成

一、整数存储

整数在内存中是以补码的形式进行存储,先写出一个数的原码

所谓原码就是直接表示这个数的大小

比如:-1原码(x86系统):10000000 00000000 00000000 00000001

                                反码:11111111 11111111 11111111 11111110

                                补码: 11111111 11111111 11111111 11111111

三种表示方法均有符号位+数值位,符号位用0表示正,1表示负,最高一位被当做符号位,其余为数值位。

最后从运行窗口显示内容,也是要将补码转换成原码进行显示的,

但计算机内的存储以及运算都是用补码进行的。

有符号整数:

正数的原码、反码、补码均相同;

负数的反码等于原码的符号位不变,其余数值位取反;补码等于反码再加1,;

同样已知一个负数的补码,可通过对补码取反再加1来求得原码。

无符号整数:

不存在符号位,均为数值位,原码、反码、补码均相同

为什么数据在内存中存放的是补码?

        原因在于,使用补码可以将符号位和数值位统一处理,同时,加法和减法也可以统一处理(cpu只有加法器),补码与原码可以相互转换,运算过程是相同的,不需要额外的硬件电路。

二、浮点数的存储?

二进制浮点数V可以表示成下面的形式:

V = (-1)^s * M * 2^E

  • (-1)^s表示符号位,当S=0;表示正数,当s=1,表示负数;
  • M表示有效数字,1<=M<2;
  • 2^E表示指数位;
  • 十进制5.0,写成二进制为101.0,1.01*2^2;S=0,E=2,M=1.01
  • IEEE754进行规定:
    • 对于32位的浮点数,最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M;
    • 对于64位的浮点数,最高的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M;
float类型浮点数的内存分配
符号位1bit指数位占8bit数值位占23bit

                 

double类型的浮点数在内存中存储
符号位1bit指数位占8bit数值位占23bit

浮点数存储的过程

  • M的存储

        对于M,要将M写成1.XXXXXX的形式,是1<=M<2;其中XXXXXX表示小数部分。

IEEE754标准规定,保存M时,默认这个数的第一位总是1,于是可以舍去,只保存XXXXXX部分,比如在保存1.01时只保存01,等到读取时,再自动把第一位的1加上去,可以节省一位有效数字,相当于能保存小数点后23位,再加上小数点前一位1,一共可保存24位有效数字。

  • E的存储

        E为一个无符号的整数,如果为8位,它取值范围为0~255;如果E为11位,它的取值为0~2047.但是科学计数法是可以出现负数的,所以IEEE754规定,存入内存时E的真实值必须再加上一个中间数,对于8位E,这个中间数是127;对于11位的E,这个中间数是1023。比如2^3,保存在32位浮点数时为3+127=130,即10000010

        E不全为0或者1

        即指数E的值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1

例如对于:

        0 01111110 00000000000000000000000

        指数E=126-127=-1,M=1.0,S=0;

        结果为:(-1)^0*1.0*2^(-1)=0.5;

        E全为0

        指数E=1-127或者(1-1023),有效数字M不再加上第一位1,而是还原成0.XXXXXX的小数,这样是为了表示±0,以及接近于0很小的数字。

        0 00000000 00100000000000000000000

        E全为1

        如果有效数字M全为0,表示±无穷大,正负取决于S

        0 11111111 00000000000000000000000

练习题

int main()
{
	int n = 9;
	float* pf = (float*)&n;
	printf("%d %f\n", n, *pf);

	*pf = 9.0;
	printf("%d %f\n", n, *pf);
	return 0;
}

读这可自行进行验证,检验学习的效果,尝试写出9和9.0在内存中分别是怎样存储的

C语言,如果你想将浮点数转换为比率或者说分数形式,通常不会直接进行这样的操作,因为浮点数是一种二进制表示法,它并不支持精确的除法。然而,如果你需要近似表示两个浮点数的比例,一种常见的做法是保留固定的小数位数,然后手动计算分子和分母。 例如,你可以创建两个变量分别存储原始数值和它们的最大公约数(GCD),然后将每个值除以GCD得到最简分数。下面是一个简单的示例: ```c #include <stdio.h> #include <math.h> // 包含gcd函数 // 计算最大公约数 int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } void floatToRatio(float num, int precision) { long long numerator = (long long)(num * pow(10, precision)); long long denominator = 1; // 初始化分母为1,便于后续除法操作 // 找到numerator的最小倍数,使得它是整数 while (denominator < numerator) { denominator *= 10; } // 计算比例 numerator /= gcd(numerator, denominator); denominator /= gcd(numerator, denominator); printf("接近的比例为: %.0f / %.0f\n", (double)numerator, (double)denominator); } int main() { float f = 3.45678; int precision = 3; // 精确到小数点后三位 floatToRatio(f, precision); return 0; } ``` 运行这个程序会输出一个接近于3.45678的分数比。请注意,这只是一个简单示例,实际应用你可能会选择更复杂的算法来处理更大范围的精度需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值