C语言中的浮点数与整数的存储方式
在 C 语言中,浮点数(float、double、long double) 和 整数(int、short、long、long long 等) 是两种不同类型的数据,它们在计算机内部的 存储方式、表示方法、精度和用途 都有显著区别。下面我们将分别详细介绍它们的存储方式。
一、整数的存储方式
1. 整数的表示
整数在计算机中是以 二进制补码(Two's Complement) 的形式存储的(对于有符号整数),无符号整数直接以二进制原码形式存储。
有符号整数(如 int, short, long)
- 最高位为符号位:
- 0表示正数或零
- 1表示负数
- 正数: 直接是其二进制表示。
- 负数: 使用 补码(Two’s Complement) 表示:
- 补码 = 反码 + 1
- 反码 = 原码按位取反(符号位不变)
例如:
十进制 | 原码 | 补码 |
5 | 00000101 | 00000101 |
-5 | 10000101 | 11111011 |
无符号整数(如 unsigned int)
- 所有位都用于表示数值,没有符号位。
- 范围是从 0 到 2^n - 1(n 是位数)
2.存储细节
整数在内存中按照 二进制补码形式从低位到高位依次存储,存储顺序还与系统的 字节序(大端/小端) 有关:
- 小端序(Little Endian,x86/x64 平台常见):低字节存放在低地址
- 大端序(Big Endian,某些网络设备和旧系统):高字节存放在低地址
例如,32 位整数0x12345678
在内存中的存储(小端):
低地址 -> 高地址:0x78 0x56 0x34 0x12
二、浮点数存储方式
1. 浮点数的表示标准:IEEE 754
C 语言中的浮点数类型(如 float, double,long double)通常遵循 IEEE 754 浮点数标准 来存储。最常用的是:
- float(单精度浮点数): 32 位
- double(双精度浮点数): 64 位
- long double(扩展精度,具体位数平台相关,可能是 80 位、96 位 或 128 位)
这里主要介绍两种最常用的,float和double。
1.1. float(32位)的 IEEE 754 格式
组成部分 | 位数 | 描述 |
---|---|---|
Sign | 1 | 符号位:0 表示正数,1 表示负数 |
Exponent | 8 | 指数部分(带偏移,偏移量是 127) |
Fraction(Mantissa) | 23 | 尾数(有效数字,隐含前导 1) |
公式:(-1)^sign × 1.M × 2^(exponent - 127)
- 1.M:尾数部分前面默认有一个隐藏的 "1."(规格化数),即实际有效位是 24 位(1 + 23)
- exponent - 127:称为 偏移表示法(bias),目的是让指数可以为正也可以为负
特殊情况:
- 若 exponent 全为 0: 表示 非规格化数(denormalized) 或 零
- 若 exponent 全为 1:
- 若 fraction 全为 0:表示 正负无穷(±Infinity)
- 若 fraction 非 0:表示 NaN(Not a Number)
1.2. double(64位)的 IEEE 754 格式
组成部分 | 位数 | 描述 |
---|---|---|
Sign | 1 | 符号位 |
Exponent | 11 | 指数部分,偏移量为 1023 |
Fraction | 52 | 尾数部分,隐含前导 1 |
公式:(-1)^sign × 1.M × 2^(exponent - 1023)
同样有非规格化数、无穷大、NaN 等特殊值处理
2.浮点数在内存中的存储
例如:float a = 12.5;
- 首先将其转化为二进制:1100.1
- 规格化:1.1001 × 2^3
- 得到:
- fraction(尾数)= 10010000000000000000000(23位,后面补零)
- exponent = 3 + 127 = 130 → 二进制 10000010
- sign = 0(正数)
- 组合:
- Sign: 0
- Exponent: 10000010
- Fraction: 10010000000000000000000
因此,最终 32 位 float 表示为:0 10000010 10010000000000000000000,也就是16进制0x41480000。
根据这个逻辑,我们发现浮点数无法精确存储,比如0.1,他在二进制中是一个无限循环的小数。
在进行存储时,一但超出固定尾数范围就会出现舍入误差。
三、总结
特性 | 整数(int, long等) | 浮点数(float, double) |
---|---|---|
表示内容 | 整数值(正、负或零) | 带小数部分的实数(可能有精度损失) |
存储格式 | 二进制原码或补码 | IEEE 754 标准(符号、指数、尾数) |
是否有精度问题 | 无 | 有(特别是小数,如 0.1 无法精确表示) |
比较操作 | 直接比较是否相等 | 不可直接比较是否相等,应考虑误差范围 |
典型用途 | 计数、索引、离散值 | 科学计算、测量值、图形坐标等连续值 |
常见类型(32位系统) | int(32位)、long(32/64位) | float(32位)、double(64位) |
内存占用(典型) | int:4 字节,long:4/8 字节 | float:4 字节,double:8 字节 |
备注:在比较两个浮点数是否相等时,需要设置误差