代码之家  ›  专栏  ›  技术社区  ›  starblue

对于未设置的值,使用IEEE754浮点NaN是一个好主意吗?

  •  13
  • starblue  · 技术社区  · 16 年前

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

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

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

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

    9 回复  |  直到 16 年前
        1
  •  11
  •   Stephen Canon    16 年前

    刚刚注意到这个问题。

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

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

        2
  •  4
  •   jskinner    16 年前

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

    • if (result == DEFAULT_VALUE) ,如果 DEFAULT_VALUE 如乔恩所说,是南。

    • 如果你不小心的话,它们也会导致距离检查的问题。考虑功能:

    bool isOutsideRange(double x, double minValue, double maxValue)
    {
        return x < minValue || x > maxValue;
    }
    

    如果x是NaN,则此函数将错误地报告x介于MinValue和MaxValue之间。

    如果你只想让用户测试一个魔法值,我建议用正无穷大或负无穷大代替NaN,因为它不带相同的陷阱。当需要NaN的属性时使用NaN,即NaN上的任何操作都会导致NaN:例如,当不希望依赖调用方检查值时,使用NaN很方便。

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

        3
  •  3
  •   Joonas Pulakka    16 年前

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

    顺便问一下,这是一个很好的问题,为什么默认初始化值通常是(例如,Java原始类型)0而不是NA。难道不是42岁吗?我想知道零的基本原理是什么。

        4
  •  3
  •   David Cournapeau    16 年前

    我认为一般来说这是个坏主意。要记住的一点是,大多数CPU处理NaN的速度要比“通常”的浮动慢得多。很难保证你在通常的环境中永远不会有NaN。我在数值计算方面的经验是,它常常带来比它值更多的麻烦。

    正确的解决方案是避免在float中编码“缺少值”,但用另一种方式来表示它。但是,这并不总是实际的,这取决于您的代码库。

        5
  •  2
  •   Chris Burt-Brown    16 年前

    小心奶奶的…如果你不小心,它们会像野火一样蔓延。

    它们是一个完全有效的浮点值,但是涉及它们的任何赋值也将等于NaN,因此它们通过代码传播。这是一个很好的调试工具,如果你抓住了它,但是如果你带来了一些东西来发布,并且在某个地方有一个边缘案例,它也可能是一个真正的麻烦。

    D使用这一点作为将浮动NaN作为默认值的理由。(我不确定是否同意。)

        6
  •  1
  •   Szundi    16 年前

    我的感觉是有点老土,但至少你用这个NaN值进行操作的其他所有数字都会给出NaN结果——当你在一个bug报告中看到一个NaN时,至少你知道你在寻找什么样的错误。

        7
  •  0
  •   Jon Skeet    16 年前

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

    记住,根据您的环境,您可能需要一种特殊的方法来检测nan(不只是使用 if (x == float.NaN) 或者不管你的等价物是什么。)

        8
  •  0
  •   old_timer    16 年前

    对我来说,这对奶奶来说是个很好的用途。真希望我能想到…

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

    我想我会用NaN代替无穷大中的一个。使用一个信号NaN并让它在第一次使用时引发一个事件可能会很好,但是到那时它太晚了,它应该在第一次使用时安静下来。

        9
  •  0
  •   Joe Erickson    16 年前

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

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

    推荐文章