浮点数的 IEEE 754 标准与内存表达

前言 项目上遇到了double类型数据精度问题,嵌入式开发和算法争论了一会有关double和float的精度问题,究竟是强转造成的精度损失更多,还是在计算的过程中精度损失更多?这个问题很显然是使用float在计算过程中造成的精度损失更多,但是面对这样的问题,不能只靠猜测,而是需要进行一系列量化的测算。 IEEE754标注中的浮点数表达公式 $$ value = (-1)^{sign} \times 2^{exponent} \times (1 + mantissa) $$ 其中,sign为符号位,exponent为指数位,mantissa为尾数位。 float float类型通常占用4个字节(32位)的内存。具体分配如下: 符号位(Sign bit):1位 指数位(Exponent):8位 尾数位(Fraction/Mantissa):23位 内存布局示例 假设我们有一个单精度浮点数3.14,它的二进制表示如下: 符号位:0 指数位:10000000 尾数位:10010001111010111000011 0 10000000 10010001111010111000011 double 符号位(Sign bit):1位 指数位(Exponent):11位 尾数位(Fraction/Mantissa):52位 内存布局 假设我们有一个双精度浮点数3.14,它的二进制表示如下: 符号位:0 指数位:10000000000 尾数位:1001000111101011100001010001111010111000010100011110101110000101 float与doule之间的转换 float转double 这种转换称为扩展转换(promotion),因为double有更多的位数来表示数字。 1.内存模型变化: float使用32位存储,而double使用64位存储。 在将float转换为double时,计算机会将float的值复制到double的尾数部分,并扩展指数部分。 由于double的尾数部分更长,可以精确表示的有效数字更多,所以这种转换通常不会损失精度。 2.转换过程 符号位保持不变。 指数位从float的8位扩展到double的11位,计算机会根据需要调整指数的偏移量。 尾数位从23位扩展到52位,不足的部分用0填充。 double 转 float 这种转换称为缩减转换(narrowing),因为float有较少的位数来表示数字。 1. 内存模型变化: double使用64位存储,而float使用32位存储。 在将double转换为float时,计算机会将double的值截断或舍入以适应float的尾数部分和指数部分。 由于float的尾数部分较短,这种转换可能会损失精度。 2.转换过程 符号位保持不变。 指数位从double的11位缩减到float的8位,计算机会调整指数的偏移量,并可能会进行舍入。 尾数位从52位缩减到23位,超出的部分会被截断或舍入,这可能导致精度损失。 这里需要注意的是,在C++中,并不是做了简单的截断,而是做了舍入操作,这也是为什么我们在实际操作中,可以观测到逢7进1 例子: float转换double 假设我们有一个float值3.14: float: 0 10000000 10010001111010111000011 ...

June 18, 2026 · 3 min · Leventure