C语言 浮点数如何存储在内存中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7644699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How are floating point numbers stored in memory?
提问by vikky
I've read that they're stored in the form of mantissa and exponent
我读过它们以尾数和指数的形式存储
I've read this documentbut I could not understand anything.
我已经阅读了这份文件,但我什么也不懂。
回答by Lindydancer
To understand how they are stored, you must first understand what they are and what kind of values they are intended to handle.
要了解它们是如何存储的,您必须首先了解它们是什么以及它们打算处理什么样的值。
Unlike integers, a floating-point value is intended to represent extremely small values as well as extremely large. For normal 32-bit floating-point values, this corresponds to values in the range from 1.175494351 * 10^-38to 3.40282347 * 10^+38.
与整数不同,浮点值旨在表示非常小的值以及非常大的值。对于普通的 32 位浮点值,这对应于1.175494351 * 10^-38到3.40282347 * 10^+38范围内的值。
Clearly, using only 32 bits, it's not possible to store every digit in such numbers.
显然,仅使用 32 位,不可能将每个数字都存储在这样的数字中。
When it comes to the representation, you can see all normal floating-point numbers as a value in the range 1.0 to (almost) 2.0, scaled with a power of two. So:
就表示而言,您可以将所有普通浮点数视为 1.0 到(几乎)2.0 范围内的值,以 2 的幂进行缩放。所以:
- 1.0 is simply 1.0 * 2^0,
- 2.0 is 1.0 * 2^1, and
- -5.0 is -1.25 * 2^2.
- 1.0 只是1.0 * 2^0,
- 2.0 是1.0 * 2^1,并且
- -5.0 是-1.25 * 2^2。
So, what is needed to encode this, as efficiently as possible? What do we really need?
那么,需要什么来尽可能高效地对其进行编码?我们真正需要的是什么?
- The sign of the expression.
- The exponent
- The value in the range 1.0 to (almost) 2.0. This is known as the "mantissa" or the significand.
- 表达式的符号。
- 指数
- 1.0 到(几乎)2.0 范围内的值。这被称为“尾数”或有效数。
This is encoded as follows, according to the IEEE-754 floating-point standard.
根据 IEEE-754 浮点标准,其编码如下。
- The sign is a single bit.
- The exponent is stored as an unsigned integer, for 32-bits floating-point values, this field is 8 bits. 1 represents the smallest exponent and "all ones - 1" the largest. (0 and "all ones" are used to encode special values, see below.) A value in the middle (127, in the 32-bit case) represents zero, this is also known as the bias.
- When looking at the mantissa (the value between 1.0 and (almost) 2.0), one sees that all possible values start with a "1" (both in the decimal and binary representation). This means that it's no point in storing it. The rest of the binary digits are stored in an integer field, in the 32-bit case this field is 23 bits.
- 符号是一位。
- 指数存储为无符号整数,对于 32 位浮点值,该字段为 8 位。1 代表最小的指数,“all one - 1”代表最大的指数。(0 和“全一”用于对特殊值进行编码,见下文。)中间的值(127,在 32 位情况下)表示零,这也称为偏差。
- 在查看尾数(介于 1.0 和(几乎)2.0 之间的值)时,您会看到所有可能的值都以“1”开头(十进制和二进制表示)。这意味着存储它没有意义。其余的二进制数字存储在整数字段中,在 32 位情况下,该字段为 23 位。
In addition to the normal floating-point values, there are a number of special values:
除了普通的浮点值之外,还有一些特殊的值:
- Zero is encoded with both exponent and mantissa as zero. The sign bit is used to represent "plus zero" and "minus zero". A minus zero is useful when the result of an operation is extremely small, but it's still important to know from which direction the operation came from.
- plus and minus infinity -- represented using an "all ones" exponent and a zero mantissa field.
- Not a Number (NaN) -- represented using an "all ones" exponent and a non-zero mantissa.
- Denormalized numbers -- numbers smaller than the smallest normal number. Represented using a zero exponent field and a non-zero mantissa. The special thing with these numbers is that the precision (i.e. the number of digits a value can contain) will drop the smaller the value becomes, simply because there is not room for them in the mantissa.
- 零用指数和尾数编码为零。符号位用于表示“加零”和“减零”。当操作的结果非常小时,负零很有用,但了解操作来自哪个方向仍然很重要。
- 加减无穷大——使用“全一”指数和零尾数字段表示。
- 不是数字 (NaN) - 使用“全一”指数和非零尾数表示。
- 非规范化数字——小于最小正常数字的数字。使用零指数字段和非零尾数表示。这些数字的特殊之处在于精度(即一个值可以包含的位数)会随着值变得越小而下降,仅仅是因为尾数中没有它们的空间。
Finally, the following is a handful of concrete examples (all values are in hex):
最后,以下是一些具体示例(所有值均以十六进制表示):
- 1.0 : 3f800000
- -1234.0 : c49a4000
- 100000000000000000000000.0: 65a96816
- 1.0 : 3f800000
- -1234.0:c49a4000
- 100000000000000000000000.0:65a96816
回答by Wyzard
In layman's terms, it's essentially scientific notationin binary. The formal standard (with details) is IEEE 754.
回答by Totonga
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);
Is an example how memory is set up if compiler uses IEEE 754 double precision which is the default for a C double on little endian systems (e.g. Intel x86).
如果编译器使用 IEEE 754 双精度,这是小端系统(例如 Intel x86)上 C 双精度的默认值,则是如何设置内存的示例。
Here it is in C based binary form and better read wikipedia about double precisionto understand it.
这里是基于 C 的二进制形式,更好地阅读 关于双精度的维基百科来理解它。
回答by Keith Thompson
There are a number of different floating-point formats. Most of them share a few common characteristics: a sign bit, some bits dedicated to storing an exponent, and some bits dedicated to storing the significand (also called the mantissa).
有许多不同的浮点格式。它们中的大多数都有一些共同的特征:一个符号位,一些专用于存储指数的位,以及一些专用于存储有效数(也称为尾数)的位。
The IEEE floating-point standard attempts to define a single format (or rather set of formats of a few sizes) that can be implemented on a variety of systems. It also defines the available operations and their semantics. It's caught on quite well, and most systems you're likely to encounter probably use IEEE floating-point. But other formats are still in use, as well as not-quite-complete IEEE implementations. The C standard provides optionalsupport for IEEE, but doesn't mandate it.
IEEE 浮点标准试图定义可以在各种系统上实现的单一格式(或者更确切地说是几种大小的格式集)。它还定义了可用的操作及其语义。它非常流行,您可能遇到的大多数系统都可能使用 IEEE 浮点数。但其他格式仍在使用中,以及不完全完整的 IEEE 实现。C 标准为 IEEE提供了可选支持,但没有强制要求。
回答by mouviciel
The mantissa represents the most significant bits of the number.
尾数代表数字的最高有效位。
The exponent represents how many shifts are to be performed on the mantissa in order to get the actual value of the number.
指数表示要对尾数执行多少次移位才能获得数字的实际值。
Encoding specifies how are represented sign of mantissa and sign of exponent (basically whether shifting to the left or to the right).
编码指定如何表示尾数符号和指数符号(基本上是向左移动还是向右移动)。
The document you refer to specifies IEEE encoding, the most widely used.
您参考的文档指定了使用最广泛的 IEEE 编码。
回答by xanatos
I have found the article you referenced quite illegible (and I DO know a little how IEEE floats work). I suggest you try with the Wiki version of the explanation. It's quite clear and has various examples:
我发现您引用的文章难以辨认(而且我确实知道 IEEE 浮点数是如何工作的)。我建议您尝试使用 Wiki 版本的解释。它很清楚,并有各种示例:
http://en.wikipedia.org/wiki/Single_precisionand http://en.wikipedia.org/wiki/Double_precision
http://en.wikipedia.org/wiki/Single_precision和http://en.wikipedia.org/wiki/Double_precision

