C中的无序浮点比较

Unordered floating point comparisons in C

C 中的默认浮点比较(例如 3.0 < 5.0)是有序的,即如果参数之一是 NaN,则产生 false。但是,编译器和处理器也有无序比较。例如,在 LLVM IR 中,fcmp instruction 都有有序和无序的变体。 C99 有一些测试 NaN 的函数。但是,除此之外我没有找到其他无序比较操作。是否有提供无序浮点比较的任何 GNU 扩展(或其他标准库函数)?

到目前为止,我只能通过检查相反的条件来实现它们。例如,为了实现一个无序的 a >= b 比较,我写了一个有序的 !(a < b) ,LLVM 最终简化为一个无序的比较 fcmp uge double %1, %2.

However, apart from that I did not find other unordered comparison operations. Are there any GNU extensions (or other standard library functions) that offer unordered floating point comparisons?

正如@user2357112 在评论中观察到的那样,"unordered floating-point comparisons" 不是问题。这个词甚至没有意义。您似乎想要评估的是 "x is less than y or the two are unordered".

形式的谓词

符合标准的 C 实现不能随意添加运算符,即使作为扩展也是如此。原则上,他们可以为现有运算符定义额外的含义,但我不知道有任何实现可以提供您正在寻找的特定操作。正如您已经发现的那样,将 C 的现有运算符用于此目的非常简单:

So far, I only could implement them by checking for the opposite condition. For example, to implement an unordered a >= b comparison, I instead wrote an ordered !(a < b)

Update:问题在于,当其中一个操作数为 NaN(并且 FP 异常未被禁用)时,这些比较将引发浮点异常。但你很幸运!从C99开始,有standard macros implementing the comparisons you seek。这些保证只计算一次参数,并且不会引发浮点异常。

当然,如果您希望能够在代码中更清楚地表达您明确适应 NaN,那么您始终可以为其编写宏:

#define GE_OR_UNORDERED(x, y) (!((x) < (y)))

// ...

if (GE_OR_UNORDERED(a, b)) // ...

另请注意,所有这些都在很大程度上依赖于实施细节。尽管 C 认识到 可能性 实数类型可以容纳不表示浮点数的值,例如 NaN,但它并不要求它们这样做,也没有定义行为对这些值的关系或算术运算。虽然现在大多数实现都使用 IEEE-754 浮点格式和运算,但它们并不是必须这样做的,而且在历史上,有些实现也没有这样做。