Inhowfar做IEEE754浮动满足LessThanComparable吗?

时间:2016-10-10 21:07:35

标签: c++ floating-point language-lawyer ieee-754

TL; DR IEEE754浮点值包括 NaN是否满足LessThanComparable

具体来说,问题“Why does Release/Debug have a different result for std::min?”让我抬头LessThanComparable

  

该类型必须与<运算符和结果应该有标准   语义。

     

要求

     

如果

,则类型T满足LessThanComparable      

鉴于

     
      
  • a,b和c,类型T或const T
  • 的表达式   
     

以下表达式必须有效且具有指定的表达式   效果

     

与以下属性建立strict weak ordering关系   (...)

我在the standard中仔细检查了它,似乎它在那里基本相同,我查看了严格弱序的维基百科def

Some think包含NaN的IEEE浮点值集合满足这个概念:任何一方与NaN的任何比较总是会产生错误,但是我一直在查看定义,NaN是否存在strict weak ordering

一点对我来说是显而易见的

维基百科提供的列表:

  • 对于S中的所有x,不是x< x(反射性)。
  • 对于S中的所有x,y,如果x <那么y&lt; x(不对称)。 see below
  • 对于S中的所有x,y,z,如果x < y和y&lt; z然后x&lt; z(及物性)。
  • 对于S中的所有x,y,z,如果x与y无法比较(x

似乎维基百科上定义的严格弱排序公理明确地提出了可能的incomparable值:NaN似乎是一个很好的候选者?

另一方面,标准说:(25.5 / 4)

  

如果我们将equiv(a, b)定义为!comp(a, b) && !comp(b, a),那么   要求是comp和equiv都是传递关系:

     

(4.1) - comp(a, b) && comp(b, c)隐含comp(a, c)

     

(4.2) - equiv(a, b) && equiv(b, c)隐含equiv(a, c)

根据这些定义,equiv(x, NaN)始终为true(因为!comp(a, NaN)==true !comp(Nan, a)==true:与Nan的比较产生错误,否定则产生真)

但显然(4.2)不满意,例如:

 equiv(3.0, NaN) && equiv(NaN, 7.0) **does not** imply equiv(3.0, 7.0)

标准定义的不是严格的弱排序,或者 - 更可能确实 - 我在这里错过了什么?

3 个答案:

答案 0 :(得分:8)

严格的弱排序要求存在强排序的等价类。 IEEE754不是这样。

问题不在于存在多个相互等效的NaN值,而是整个NaN类相对于实线无序。

违反(4.2)会导致您从维基百科引用的第四个项目符号中的测试也失败(让y成为NaN)。

对于严格弱排序中允许的不可比性的示例,请考虑符号幅度整数。然后:

  

-4&lt; -3&lt; -2&lt; -1&lt; {-0,+ 0}&lt; +1&lt; +2&lt; +3&lt; 4

-0 < +0+0 < -0都不是,所以排序很弱。但是由这些等价值形成的阶级对所有其他阶段都是有序的。

答案 1 :(得分:2)

IEEE754浮点值(包括NaN 不满足LessThanComparable。

如果您从维基百科中取得第4个项目符号并将无法比较的替换为equiv,则其条件与标准中的相同。

这是一个很好的答案,基本上可以回答我所有的C ++问题。这样:

https://stackoverflow.com/a/8097097/321013

它甚至引用了std中与我在上面问题末尾所做的相同的段落:

  
    

如果我们将equiv(a,b)定义为!comp(a,b)&amp;&amp; !comp(b,a),然后是       要求是comp和equiv都是传递关系......       等效(a,b)&amp;&amp; equiv(b,c)意味着equiv(a,c)

  
     

a = 0.0,b = NaN,c = 1.0,comp = std::less<double>()

失败

它也解决了一个有趣的问题。要求:

  

我一直认为有点奇怪的是标准   表示关键类型的要求,而不是表达   添加到容器的实际键值。我相信你可以   选择将其视为不保证map<double, int>具有此功能   如果实现支持NaN,则根本定义行为,   无论您是否实际向实例添加NaN。

答案 2 :(得分:1)

您似乎在说维基百科的定义允许使用NaN,但标准的定义却没有。我不认为你是对的。来自维基百科的定义:

  

对于S中的所有x,y,z,如果x与y无法比较(x

假设x为3.0,y为NaN,z为7.0。 x与y无法比较。 y与z无法比较。 x 与z无法比较。