[C/C++] float和double类型的内存分布和比较方法

C/C++浮点数详解
本文详细介绍了C/C++中的浮点数类型float和double的内部存储结构,包括符号位、指数和尾数的分配及意义。同时,讨论了浮点数表示的精度问题及其在比较操作时需要注意的事项。

 

C/C++的浮点数据类型有float和double两种。
类型float大小为4字节,即32位,内存中的存储方式如下:

 符号位(1 bit)
指数(8 bit)
尾数(23 bit)

类型double大小为8字节,即64位,内存布局如下:

符号位(1 bit)
指数(11 bit)
尾数(52 bit)

 
符号位决定浮点数的正负,0正1负。
指数和尾数均从浮点数的二进制科学计数形式中获取。
如,十进制浮点数2.5的二进制形式为10.1,转换为科学计数法形式为(1.01)*(10^1),由此可知指数为1,尾数(即科学计数法的小数部分)为01。
根据浮点数的存储标准(IEEE制定),float类型指数的起始数为127(二进制0111 1111),double类型指数的起始数为1023(二进制011 1111 1111),在此基础上加指数,得到的就是内存中指数的表示形式。尾数则直接填入,如果空间多余则以0补齐,如果空间不够则0舍1入。所以float和double类型分别表示的2.5如下(二进制):

符号位
指数
尾数
0
1000 0000
010 0000 0000 0000 0000 0000
0
100 0000 0000
0100 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000

浮点数2.5可以用二进制小数准确表示(2.5=1*(2^1)+0*(2^0)+1*(2^-1)),但很多小数不可以准确表示,其二进制形式的小数部分会无限循环,如浮点数-1.2表示如下(二进制):

符号位
指数
尾数
1
0111 1111
0011 0011 0011 0011 0011 010
1
011 1111 1111
0011 0011 0011 0011 0011 0011 0011
0011 0011 0011 0011 0011 0011

由于对无限循环尾数的截取遵循0舍1入,尾数的第21~24位为0011,第53~56位为0011,而float尾数容量为23位,double尾数容量为52位,所以,float形式的最后三位因进位而成010,double形式则没有进位发生。
 
类型float和double通过==,>,<等比较不会引起编译错误,但是非常可能得到错误的结果。这是因为它们的内存分布不同,不可以直接比较。正确的方法是转换为同一类型后比较两者差值,如果结果小于规定的小值,则视为相等。
如,一个比较double的实现:
另外,本文参考了如下webs:
 
P.S.
1)
IEEE浮点数标准:     4字节浮点数:1位符号位,8位阶数(基数为127的移码),23位尾数;     8字节浮点数:1位符号位,11位阶数(基数为1023的移码),52位尾数
2 )
在VC中: float数值范围约在 -10e38~10e38,并提供7位有效数字位,绝对值小于10e38地数被处理成零值 double数值范围约在-10e308~10e308,并提供15~16位有效数字,绝对值小于10e308地数被处理成零值
### C++ 中 `float` `double` 的区别与使用场景 #### 一、存储大小 在 C++ 中,`float` 类型通常占用 4 字节(32 位),而 `double` 类型则占用 8 字节(64 位)。这种差异直接影响到它们能表示的数据范围精度[^2]。 #### 二、精度比较 由于 `double` 占用更多的字节,因此它具有更高的精度,能够表示更大的数值范围以及更小的增量单位。具体来说: - **`float`**:提供约 7 位有效数字。 - **`double`**:提供约 15 至 16 位有效数字[^3]。 #### 三、运算速度 因为 `float` 所需的存储空间较小,在某些硬件架构上可能带来更快的操作效率。然而现代计算机中,`double` 的性能差距已经显著缩小,尤其是在支持 SIMD 指令集的情况下[^4]。 #### 四、适用场合 当程序设计需要较高的精确度或者处理非常大/非常小的数量级时推荐采用 `double` 数据类型;而对于那些对内存敏感的应用环境,则可以选择使用 `float` 来减少资源消耗[^1]。 以下是简单的代码示例展示如何声明并初始化这两种类型的变量: ```cpp #include <iostream> using namespace std; int main() { // 定义 float 变量 float fValue = 1.23f; // 定义 double 变量 double dValue = 1.23e-10; cout << "Float Value: " << fValue << endl; cout << "Double Value: " << dValue << endl; return 0; } ``` 此段代码展示了两种不同方式来赋初值给浮点数——通过附加字母 'f' 明确指出该常量应被解释成单精度形式(`float`) 或者让编译器默认将其视为双精度 (`double`) 数值。 ### IEEE 754标准下的内部结构 依据IEEE 754规定, `float` `double` 都由三个部分组成: 符号位(Sign), 阶码(Exponent) 尾数(Fraction/Mantissa). 对于上述提到的不同长度实现如下表所示: | 类型 | 符号位 (S) | 阶码(E) | 小数(M) | |-----------|------------|-------------|---------------| | Float | 1 bit | 8 bits | 23 bits | | Double | 1 bit | 11 bits | 52 bits | 这进一步说明了为何 `double` 能够达到更好的准确性. ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值