C中的无序浮点比较

时间:2016-05-18 16:30:48

标签: c floating-point llvm llvm-ir comparison-operators

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

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

1 个答案:

答案 0 :(得分:3)

  

然而,除此之外我没有找到其他无序的比较操作。是否有任何GNU扩展(或其他标准库函数)提供无序浮点比较?

正如@ user2357112在评论中观察到的那样,“无序的浮点比较”不是一回事。这个词甚至没有意义。你似乎想要评估的是“x小于y或两者是无序的”形式的谓词。

遵守C实现并不是自由添加运算符,即使是作为扩展。原则上,它们可以为现有运营商定义其他含义,但我不知道任何提供您正在寻找的具体操作的实现。正如您已经发现的那样,使用C的现有运算符非常简单:

  

到目前为止,我只能通过检查相反的条件来实现它们。例如,要实现无序a >= b比较,我改为编写了一个有序的!(a < b)

更新:问题在于,当其中一个操作数为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浮点格式和操作,但它们不是必须这样做的,而且从历史上看,有些则没有。