在C++中,!(x<y)和x>=y有什么区别?

6

在阅读 EASTL 的代码时,我发现了一行奇怪的代码。以下链接显示了该文件,并标明了1870行。

https://github.com/paulhodge/EASTL/blob/master/include/EASTL/algorithm.h

在这行代码中,if(!(value < *i))。注释说“我们总是用<或==来表示值比较,但没有任何解释为什么要这样做。还有其他一些地方也放置了相同的注释,但没有任何解释。”

写这样的比较有任何好处吗(也许有我忽略的上下文)?如果没有,为什么 EASTL 的作者故意以这种特定的方式编写它,甚至还要注意到它并加以评论?这里只是出于一致性的原因吗?


1
在浮点数中,它们是不同的,因为与 NaN 的比较总是返回 false。 - Mysticial
听起来像是针对特定处理器/汇编器/编译器类型的优化。这段代码是针对特定的处理器/编译器等吗? - Adrian Cornish
@AdrianCornish:这与优化无关,而与C++不会默认将运算符彼此关联有关。 - Matthieu M.
1
基本上,它应该只意味着EASTL遵循C++标准STL部分的约定。 - visitor
4个回答

11

这意味着您只需为容器值类型提供<==即可。这也意味着您减少了这些类型的可变性(因为所有算法都使用!(a<b)表示a>=b!(a==b)表示a!=b);否则,您可能会返回不一致的结果,例如>=!=


8
在C++中,您可以重载<运算符,使其行为与>=的相反方式不同,因此不能保证它们等效。
此外,在任何IEEE浮点实现中,NaN < NaN为false,但是NaN >= NaN也是false,因此!(NaN < NaN)为true,即使NaN >= NaN为false。

1

我看到至少有一个区别。如果其中一个数字是 QNAN(浮点数 0/0),那么如果 a 或 b 中的任何一个是 QNAN,则!(a < b) 总是返回 TRUE,而对于 a>=b,它总是返回 false


实际上,这种行为非常令人讨厌。在数学上,"<" 的一个属性是反对称性。这意味着 !(a < b) 意味着 b < a。人们有意选择违反这个属性,让我感到困惑,它会扰乱许多算法... - Matthieu M.
@SteveJessop:是的,抱歉,它有点偏离了。真正的关系是:(!(a < b)&& !(b < a))=> a == b - Matthieu M.
@Matthieu:确实很烦人,但你对反对称的定义是错误的。考虑 a == b,那么 !(a<b) 并不意味着 b<a。因此,即使对于不奇怪的类型,也不要使用该定义 :-) 正确的定义是 a < b 意味着 !(b<a),事实上 NaN 会自动满足这个条件,因为 lhs 从来不为真。它在 < 方面缺少的属性是等价关系不具有传递性,但是 float 上的 < 是一个严格的偏序关系。 - Steve Jessop
2
我认为NaN在浮点数定义的排序之外的理由是,IEEE提供了足够的保证,只要小心,就可以避免生成NaN。不要对负数取平方根等。如果你愿意,你可以假装所有生成NaN的操作都有未定义行为,那么你只需要担心NaN输入对公共库函数的含义即可。 - Steve Jessop

1

只使用小于运算符,就可以模拟所有其他比较运算符。这使得它更加一致,并允许您在需要参数化比较时使用单个模板参数。例如,标准排序容器和算法使用std::less<T>作为默认的模板比较器。

operation  equivalent
x < y      x < y
x > y      y < x
x <= y     !(y < x)
x >= y     !(x < y)
x == y     !(x < y) && !(y < x)
x != y     (x < y) || (y < x)

对于那些不考虑顺序的操作,使用运算符==会更简单高效。


标准库还使用equal_to(==)进行相等性检查。 - visitor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接