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

  • C/C++ 程序中的浮点数

计算机程序中的浮点数的表示方式也类似上面提到的方式.只是在计算机中是以  2 为底数,而不是 10.

需要注意
  1. Intel CPU 是采用 little-endian ( The most significant byte is on the right end of a word. ) 所以在观察内存时是需要反过来读的.
  2. 有一些编译器 和 平台支持精度更高的 Double-Extended
  • C/C++ 编译器中的浮点数表示方式如下表所示.
   符号位 ( Sign )  指数 ( Exponent )  尾数 ( Mantissa )
 单精度浮点数 ( float )  1 [31]  8 [30-23]  23 [22-00]
 双精度浮点数 ( double)  1 [63]  11 [62-52]  52 [51-00]
  •  
    •  
      • 符号
符号位占用一位.在最高位. 0 表示正数. 1 表示负数.
  •  
    •  
      • 指数
以 float 为例 指数位 占用 8 为, 他的表示范围是. -127 ~ +128. 但是 -127 和 +128 这 2 个数字是保留用作表示特殊状态的. ( -127 用来表示 这个是 0, 即 Zero 状态. +128 一般用来表示 NaN 状态. NaN 是指  Not a Number. 不是一个实际的数字. )
 
这 8 位在做计算是要注意范围是从 -127 ~ +128 的,所以在计算是要减去 127.
比如有这 8位的指数2进制如下:
10000000
 
所以这个指数表示的是: 10000000b = 128 考虑到范围所以 128 - 127 = 1
 
当精度为 double 时也是这样的,只是表示范围是 -1023 ~ +1024 .
 
  •  
    •  
      • 尾数
尾数又叫有效位数 ( Significand ), 他和 科学记数中的尾数一样是用来表示这个数字的大小 和 精确度的.
尾数的格式是 1.F. 其中 F 是对应的 小数位. 整数部分的 1 是在计算中省略的.
 
  • 举实际例子来说
比如: 
有十进制  +5.5, 则有
+5.5 = 1.375 × 2 2

随后把 尾数换算成 2 进制.
1.375 = 1 .011 B  ( 即,  1 × 2 1 + 1 × 2 -2 + 1 × 2 -3 )

由于 float 中尾数占用 23 位,所以要不齐那些无用的 0, 就得出 尾数为.
1 .01100000000000000000000 

指数位是 2,由于 float 变换范围是 -127 ~ +128 占用 8 位. 所以指数位应该等于 2 + 127 = 10000001b

所以就有 2 进制表示.
 符号位 ( Sign )  指数 ( Exponent )  尾数 ( Mantissa )
 0 10000001 01100000000000000000000

 

得出 +5.5 = 01000000101100000000000000000000B = 0x40B00000
因为 little-endian 的关系,所以在内存中观察是反序的,即 [ 00 00 B0 40 ]
  • 开发时的注意事项

    • 比较操作
不可将浮点变量用 “==” 或 “!=” 与任何数字比较.千万要留意,无论是float 还是double 类型的变量,都有精度限制.
所以一定要避免将浮点变量用 “==” 或 “!=” 与数字比较,应该设法转化成 “>=” 或 “<=” 形式.
 
假设浮点变量的名字为x,应当将
if (x == 0.0) // 隐含错误的比较
转化为
if ((x>=-PRECISION) && (x<=PRECISION))
其中PRECISION 是允许的误差(即精度).如果不是和 0 比较,则可用 与比较值之间的差值的绝对值与精度比较.比如: x 与 y 的比较可写成 fabs( x - y ) < PRECISION

  •  
    • 位运算
正常情况下不要用 浮点数去做位运算.即使是你清楚浮点的存储结构.
理由有二. 1. 不便于他人维护代码. 2. 可能有编译器不兼容问题.

你可能感兴趣的:(浮点数)