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

时间:2011-10-04 07:47:17

标签: c floating-point

我读过它们以尾数和指数

的形式存储

我读过this document但我什么都听不懂。

7 个答案:

答案 0 :(得分:39)

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

与整数不同,浮点值旨在表示极小值和极大值。对于正常的32位浮点值,这对应于从 1.175494351 * 10 ^ -38 3.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 ones”用于编码特殊值,见下文。)中间的值(127,在32位情况下)表示零,这也称为 bias
  • 当查看尾数(1.0和(差不多)2.0之间的值)时,可以看到所有可能的值都以“1”开头(十进制和二进制表示)。这意味着存储它没有意义。其余的二进制数字存储在整数字段中,在32位情况下,该字段为23位。

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

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

最后,以下是一些具体的例子(所有值都是十六进制):

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

答案 1 :(得分:7)

用外行人的话说,二进制基本上是scientific notation。正式标准(详情)为IEEE 754

答案 2 :(得分:5)

  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);

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

这是基于C的二进制形式,更好的阅读 wikipedia about double precision了解它。

答案 3 :(得分:2)

有许多不同的浮点格式。它们中的大多数具有一些共同特征:符号位,一些专用于存储指数的位,以及一些专用于存储有效位数的位(也称为尾数)。

IEEE浮点标准试图定义可在各种系统上实现的单一格式(或几种大小的格式集)。它还定义了可用的操作及其语义。它很流行,你可能遇到的大多数系统都可能使用IEEE浮点数。但其他格式仍在使用,以及不完全的IEEE实现。 C标准为IEEE提供可选支持,但不强制要求。

答案 4 :(得分:1)

尾数表示该数字的最高有效位。

指数表示要对尾数执行的移位数,以获得该数字的实际值。

编码指定如何表示尾数的符号和指数的符号(基本上是向左还是向右移动)。

您所引用的文件指定使用最广泛的IEEE编码。

答案 5 :(得分:1)

我发现你引用的文章很难辨认(我知道IEEE浮动的工作方式)。我建议你尝试使用维基版本的解释。这很清楚,并有各种例子:

http://en.wikipedia.org/wiki/Single_precisionhttp://en.wikipedia.org/wiki/Double_precision

答案 6 :(得分:-1)

它是实现定义的,尽管到目前为止IEEE-754是最常见的。

确保使用IEEE-754:

  • 在C中,使用#ifdef __STDC_IEC_559__
  • 在C ++中,使用std::numeric_limits<float>::is_iec559常量

我已经在IEEE-754上写了一些指南: