浮点数如何存储在内存中?

vik*_*kky 33 c floating-point

我读过它们以尾数和指数的形式存储

我读过这份文件,但我什么都听不懂.

Lin*_*cer 47

要了解它们的存储方式,您必须首先了解它们的含义以及它们要处理的值.

与整数不同,浮点值旨在表示极小的值以及极大的值.对于正常的32位浮点值,这对应于1.175494351*10 ^ -383.40282347*10 ^ + 38范围内的值.

显然,仅使用32位,不可能以这样的数字存储每个数字.

当涉及到表示时,您可以将所有正常的浮点数看作1.0到(几乎)2.0范围内的值,以2的幂进行缩放.所以1.0就是1.0*2 ^ 0.2.0是1.0*2 ^ 1.-5.0是-1.25*2 ^ 2.

那么,需要尽可能有效地对此进行编码吗?我们真正需要什么?

  • 表达的标志.
  • 指数
  • 值范围为1.0到(几乎)2.0.这被称为"尾数"即有效数.

根据IEEE-754浮点标准,其编码如下.

  • 标志是一个位.
  • 指数存储为无符号整数,对于32位浮点值,该字段为8位.1表示最小指数,"全1 - 1"表示最大指数.(0和"all 1"用于编码特殊值,见下文.)中间的值(127,在32位情况下)表示零,这也称为偏差.
  • 当查看尾数(1.0和(几乎)2.0之间的值)时,可以看到所有可能的值都以"1"开头(十进制和二进制表示).这意味着存储它没有意义.其余的二进制数字存储在整数字段中,在32位情况下,该字段为23位.

除了正常的浮点值之外,还有许多特殊值:

  • 零用代数和尾数编码为零.符号位用于表示"加零"和"减零".当操作的结果非常小时,减零是有用的,但是知道操作来自哪个方向仍然很重要.
  • 加号和减号无穷大 - 使用"全1"指数和零尾数字段表示.
  • 不是数字(NaN) - 使用"全1"指数和非零尾数表示.
  • 非规格化数字 - 小于最小正常数字的数字.使用零指数字段和非零尾数表示.这些数字的特殊之处在于精度(即值可以包含的位数)将随着值变小而下降,这仅仅是因为尾数中没有空间.

最后,以下是一些具体示例(所有值均为十六进制):

  • 1.0:3f800000
  • -1234.0:c49a4000
  • 100000000000000000000000.0:65a96816


Wyz*_*a-- 12

用外行人的话说,它基本上是二进制的科学记数法.正式标准(详情)是IEEE 754.

  • +1但是Wiki不是正式标准,它至多是正式标准的解释:-) :-) (7认同)
  • 而且C不需要IEEE浮点数. (4认同)

Tot*_*nga 7

  typedef struct {
      unsigned int mantissa_low:32;     
      unsigned int mantissa_high:20;
      unsigned int exponent:11;        
      unsigned int sign:1;
    } tDoubleStruct;

double a = 1.2;
tDoubleStruct* b = reinterpret_cast<tDoubleStruct*>(&a);
Run Code Online (Sandbox Code Playgroud)

如果编译器使用IEEE 754双精度(这是当今大多数系统上C双精度的默认值),那么如何设置内存就是一个例子.

这里是基于C的二进制形式,更好地阅读 维基百科有关双精度的理解.