13

将 IEEE754 浮点 NaN(非数字)用于非数学原因未定义的值是一个好主意吗?

在我们的例子中,它们尚未设置,因为尚未从其他设备接收到这些值。上下文是使用 IEC1131 REAL32 值的嵌入式系统。编辑:编程语言是 C,所以我们很可能使用来自 C99 的 NAN 和 isnanf(x)。尽管我们可能需要一些额外的扭曲才能将它们放入我们的操作系统兼容层。

编程语言的默认设置似乎是用正零初始化浮点变量,其内部表示全为零。这对我们来说是不可用的,因为 0 在有效值的范围内。

使用 NaN 似乎是一个干净的解决方案,但也许它比它的价值更麻烦,我们应该选择其他值吗?

4

9 回答 9

11

刚注意到这个问题。

这是 IEEE 754 委员会考虑的 NaN 用途之一(我是委员会成员)。NaN 在算术中的传播规则使其非常有吸引力,因为如果您有一个涉及一些初始化数据的长序列计算的结果,您不会将结果误认为是有效结果。它还可以更直接地追溯您的计算,以更直接地找到您使用初始化数据的位置。

也就是说,754 委员会无法控制一些陷阱:正如其他人所指出的,并非所有硬件都支持高速 NaN 值,这可能会导致性能危害。幸运的是,在性能关键的设置中,人们并不经常对初始化数据执行大量操作。

于 2009-10-15T16:25:39.303 回答
4

NaN 是“无值”语句的合理选择(例如,D 编程语言将它们用于未初始化的值),但因为涉及它们的任何比较都是错误的,所以您会得到一些惊喜:

  • if (result == DEFAULT_VALUE),如果是 NaN,则不会按预期工作DEFAULT_VALUE,正如 Jon 所提到的。

  • 如果您不小心,它们也可能导致范围检查出现问题。考虑函数:

bool isOutsideRange(double x, double minValue, double maxValue)
{
    返回 x < 最小值 || x > 最大值;
}

如果 x 为 NaN,此函数将错误地报告 x 介于 minValue 和 maxValue 之间。

如果您只想让用户测试一个神奇的值,我建议使用正无穷或负无穷而不是 NaN,因为它没有相同的陷阱。当你想要它的属性时使用 NaN,即对 NaN 的任何操作都会导致 NaN:例如,当你不想依赖调用者检查值时,它很方便。

[编辑:我最初设法在上面输入“任何涉及它们的比较都是真的”,这不是我的意思,而且是错误的,它们都是假的,除了 NaN != NaN,这是真的]

于 2009-06-24T07:41:37.343 回答
3

正因为如此,我在类似的情况下使用了 NaN:通常的默认初始化值 0 也是一个有效值。到目前为止,NaN 工作正常。

顺便说一句,这是一个很好的问题,为什么默认初始化值通常(例如,在 Java 原始类型中)是 0 而不是 NaN。也不能是 42 或其他什么?我想知道零的基本原理是什么。

于 2009-06-24T06:30:00.117 回答
3

我认为总的来说这是一个坏主意。要记住的一件事是,大多数 CPU 对待 Nan 的速度比“通常”的浮动要慢得多。而且很难保证你在通常的环境中永远不会有 Nan。我在数值计算方面的经验是,它带来的麻烦往往多于它的价值。

正确的解决方案是避免在浮点数中编码“缺少值”,而是以另一种方式发出信号。但是,这并不总是可行的,具体取决于您的代码库。

于 2009-06-24T18:31:29.067 回答
2

小心 NaN ......如果你不小心,它们会像野火一样蔓延。

它们是浮点数的完全有效值,但涉及它们的任何赋值也将等于 NaN,因此它们会通过您的代码传播。如果您发现它作为调试工具非常好,但是如果您要发布一些东西并且某处存在边缘案例,它也可能是一个真正的麻烦。

D 将此作为将浮点数 NaN 作为默认值的基本原理。(我不确定我是否同意。)

于 2009-06-24T08:42:06.283 回答
1

我的感觉是它有点 hacky,但至少你使用这个 NaN 值进行运算的每个其他数字都会给出 NaN 作为结果——当你在错误报告中看到 NaN 时,至少你知道你在寻找什么样的错误。

于 2009-06-24T08:16:36.133 回答
0

如果您的基本需求是有一个不代表可能从设备接收到的任何数字的浮点值,并且如果设备保证它永远不会返回 NaN,那么这对我来说似乎是合理的。

请记住,根据您的环境,您可能需要一种特殊的检测 NaN 的方法(不要只使用if (x == float.NaN)或任何您的等价物。)

于 2009-06-24T06:30:27.307 回答
0

对我来说,这听起来对 nans 很有用。真希望我能想到...

当然,它们应该像病毒一样传播,这就是重点。

我想我会使用 nan 而不是无穷大之一。使用信号 nan 并让它在第一次使用时引发事件可能会很好,但是到那时它应该在第一次使用时安静下来为时已晚。

于 2009-07-10T21:26:54.973 回答
0

使用 NaN 作为默认值是合理的。

请注意,某些表达式,例如 (0.0 / 0.0),返回 NaN。

于 2009-07-10T21:34:13.337 回答