浮点数或双精度数的 NaN 和 Infinity 如何存储在内存中?

Posted

技术标签:

【中文标题】浮点数或双精度数的 NaN 和 Infinity 如何存储在内存中?【英文标题】:How are NaN and Infinity of a float or double stored in memory? 【发布时间】:2016-07-09 03:35:14 【问题描述】:

据我了解,java 会将浮点数作为具有以下属性的 32 位整数存储在内存中:

第一位用于确定符号 接下来的 8 位代表指数 最后 23 位用于存储小数

这没有为三种特殊情况留下多余的位:

NaN 正无穷 负无穷

我可以猜到负 0 可以用来存储其中一个。

这些实际上是如何在内存中表示的?

【问题讨论】:

写在常量描述0xfff0000000000000L=-Infinity0x7ff0000000000000L=+Infinity0x7ff8000000000000L=NaN中。 (这是 double 的值) 它记录在 javadoc 中 @Lashane Google 中的第一个链接这个问题:google.com/search?q=how+are+NaN+and+infinity+stored+in+memoryIMO 研究不足或没有这样的问题通常非常有用。 fortran 的等效问题:***.com/q/640109/1157054 @PascalCuoq 不,我是说仅仅因为可以通过阅读其他来源找到答案而说一个问题没有用是不正确的。在发布此问题之前,搜索 Google 的人可能必须通读有关 NaN 的 Wikipedia 文章才能找到答案。现在,可以在 Google 搜索结果的顶部找到对他们特定问题的完整、写得很好的答案,我认为总体上情况更好。 "Ask questions, get answers, no distractions" 【参考方案1】:

首先我们要了解数字在内存中是如何表示为浮点数和双精度数的。

一般数的形式为:1.M * 2^e。

(其中M称为尾数,e是excess-127中的指数)

浮点数

MSB(Most Significant bit) 用作符号位,23 到 31 的位数用于超过 127 形式的指数值,0 到 30 的位数用于存储尾数.

双打

MSB(Most Significant bit) 用作符号位,52 到 63 的位数用于超过 127 形式的指数值,从 0 到 0 的位数用于存储尾数。

所以现在我们可以理解浮点数或双精度数中的 NaN、Infinity 表示了。

NaN(不是数字)

在 NaN 的表示中,所有的指数位都是 1,尾数位可以是任何东西,无论是浮点数还是十进制数都没有关系。

无限

在 Infinity 的表示中,所有指数位都是 1,尾数位是 0,无论是浮点数还是十进制数都没有关系。 正无穷与上述相同,但符号位为0,负无穷也相同,但符号位为1。 p>

【讨论】:

【参考方案2】:

Java 使用 IEEE 754 浮点。

大多数数字以符号-指数-尾数格式表示,尾数有一个隐含的前导 1。

指数(全零和全一)字段的极值不用作正常指数值。相反,它们用于表示特殊情况。

指数字段中的所有零都用于表示太小而无法以正常格式表示的数字(包括正零和负零)。

指数中的所有1用于表示特殊值。如果尾数中的所有位都为零,则该值是正无穷大或负无穷大(由符号位指示的符号)。否则值为 NaN。

【讨论】:

【参考方案3】:

Java 指定浮点数遵循IEEE 754 标准。

这是它的存储方式:

位 0:符号位 位 1 到 11:指数 位 12 到 63:分数

现在,我用不同的 double 值执行了以下方法:

public static void print(double d)
    System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d)));

我使用这些值执行:

print(Double.NaN);
print(Double.NEGATIVE_INFINITY);
print(Double.POSITIVE_INFINITY);
print(-Double.MAX_VALUE);
print(Double.MAX_VALUE);

并得到上述值的以下输出(为便于阅读而格式化):

 NaN: 0111111111111000000000000000000000000000000000000000000000000000
-Inf: 1111111111110000000000000000000000000000000000000000000000000000
+Inf: 0111111111110000000000000000000000000000000000000000000000000000
-Max: 1111111111101111111111111111111111111111111111111111111111111111
+Max: 0111111111101111111111111111111111111111111111111111111111111111

Wikipedia explains 表示当指数字段为 all-bits-1 时,数字为 Inf 或 NaN。 Inf 的尾数为零; NaN 在尾数中至少有一位设置为 1。符号位对于 Inf 保留其正常含义,但对于 NaN 没有意义。 Java 的Double.NaN 是一个将被解释为 NaN 的特定值,但还有 253-3 个其他值。

【讨论】:

请写出你从代码中得到的实际输出——就目前而言,它永远不会打印出文本,只有二进制——或者更新你的代码以打印你所说的。另外,由于目前的情况很难快速比较,请排好序号。 您仍然无法轻松比较输出 - 您当前提供的代码可以做到这一点。请编写该代码的实际输出,或包含生成您给出的输出的代码。 正如我之前所说,代码和格式化输出是不言自明的。我失败的是理解上述评论。如果您有任何具体问题,可以将其作为关于 SO 的新问题提出,我将很乐意回答。干杯。 好吧,我将在电脑前进行编辑以显示我的意思。如果您不同意,请随时回滚。我没有问题;我试图让你改进你的答案。 我已经更正了您的输出和您对输出的解释。您的实际打印代码,无论它是什么,都会通过丢弃前导零位来误导您,导致您认为符号位已为所有内容设置。【参考方案4】:

来自here:

问。使用 IEEE 754 如何表示零、无穷大和 NaN?

A.通过将所有指数位设置为 1。正无穷大 = 0x7ff0000000000000(所有指数位 1,符号位 0 和所有尾数 位 0),负无穷 = 0xfff0000000000000(所有指数位 1, 符号位 1 和所有尾数位 0),NaN = 0x7ff8000000000000(所有 指数位 1,至少设置一个尾数位)。正零 = 全部 位 0。负零 = 所有位 0,符号位为 1 除外。

另请参阅有关 NAN, Positive Infinity and Negative Infinity 的 Javadocs。

【讨论】:

这也意味着可以有多个NaN,可以相互区分(即使它们都是NaN)。一些应用程序使用它来存储有关非数字性质的附加信息。【参考方案5】:

如Wikipedia 中所述,所有位都设置为 1 的指数用于识别这些数字。设置为 0 的分数字段用于标识无穷大(正或负,由符号标识),非零分数字段标识 NaN 值。

【讨论】:

以上是关于浮点数或双精度数的 NaN 和 Infinity 如何存储在内存中?的主要内容,如果未能解决你的问题,请参考以下文章

Python3 Infinity/NaN:十进制与浮点数

NaN 对双打意味着啥?

转换为双精度浮点数或浮点数是不是保留无穷大和 NaN?

可以采用整数或浮点数或双精度数或任何其他可转换为浮点数的 C++ 函数

在 C 中,如何将浮点数或双精度数除以 2 的 i 次幂?

数据类型