2011-10-04 45 views
16

我读过他们存储在尾数和指数的形式浮点数如何存储在内存中?

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

+1

您链接到该文件解释它,而明确。你觉得什么特别难以理解? –

+1

@MichaelBorgwardt不,现在还不清楚。它解释了在介绍一个需要这个解释的问题之后指数是如何被存储的('但是如果这个数字是零?'......哦,亲爱的')。就像那些犯罪故事,其中的窍门是他们没有向你显示所有的信息,但故事中的主角知道他们。 – xanatos

回答

25

,了解他们是如何存储,你必须先了解它们是什么,什么样的,他们的目的是处理值。

与整数不同,浮点值旨在表示非常小的值以及非常大的值。对于正常的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”代表最大的指数。 (0和“全1”用于编码特殊值,见下文)。中间值(127,在32位情况下)表示零,这也被称为偏差
  • 查看尾数(1.0和(几乎)2.0之间的值)时,可以看到所有可能的值都以“1”开头(都是十进制和二进制表示形式)。这意味着存储它是没有意义的。其余的二进制数字存储在整数字段中,在32位的情况下,该字段是23位。

除了正常浮点值,也有一些特殊值:

  • 零编码有两个指数和尾数为零。符号位用于表示“加零”和“减零”。当一个操作的结果非常小时,减零是有用的,但是知道操作来自哪个方向仍然很重要。
  • 正负无穷 - 用“全1”指数和零尾数字段表示。
  • 非数字(NaN) - 使用“全部1”指数和非零尾数表示。
  • 非标准化数字 - 小于最小正常数字的数字。使用零指数字段和非零尾数表示。具有这些数字的特殊情况是,精度(即数值可以包含的数字的数量)会降低数值越小,这仅仅是因为在尾数中没有空间。

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

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

通俗地说,它基本上是二进制的scientific notation。正式标准(详情)为IEEE 754

+5

+1但维基不是正式标准,它至多是对正式标准的解释:-) :-) – xanatos

+4

而C不需要IEEE浮点数。 –

3
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来理解它。

+1

这是一种可能性,但不是唯一的可能性。 –

2

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

IEEE浮点标准试图定义可以在各种系统上实现的单一格式(或更确切地说几种尺寸格式)。它还定义了可用的操作及其语义。它被很好地吸引住了,你可能遇到的大多数系统可能都使用IEEE浮点。但其他格式仍在使用中,以及不完整的IEEE实现。 C标准提供可选的支持IEEE,但没有强制它。

1

尾数代表数字的最高有效位。

指数代表要在尾数上执行多少次换档才能获得数字的实际值。

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

您引用的文档指定了使用最广泛的IEEE编码。

0

它是实现定义的,尽管IEEE-754是迄今为止最常见的。

要确保IEEE-754使用:

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