有没有任何浮点比较“异常”?

时间:2010-09-13 08:53:30

标签: comparison floating-point

如果我比较两个浮点数,是否存在a>=b不等同于b<=a!(a<b),或者a==b不等于{{}的情况1}}和b==a

换句话说:比较总是“对称的”,这样我可以通过交换操作数和镜像操作符来获得相同的结果吗?它们是否总是“可否定的”,这样否定运算符(例如!(a!=b)>)相当于将逻辑NOT(<=)应用于结果?

5 个答案:

答案 0 :(得分:7)

假设IEEE-754浮点:

  • a >= b始终等同于b <= a。*
  • a >= b相当于!(a < b),除非ab中的一个或两个是NaN。
  • a == b始终等同于b == a。*
  • a == b相当于!(a != b),除非ab中的一个或两个是NaN。

更一般地说:三分法不适用于浮点数。相反,相关财产包含[IEEE-754(1985)§5.7]:

  
    

四种相互排斥的关系是可能的:小于,等于,大于和无序。当至少一个操作数是NaN时,出现最后一种情况。每个NaN都应该将无序与包括其自身在内的所有东西进行比较。

  

请注意,这并非真正的“异常”,而是将算法扩展为试图在可能的情况下保持与实际算术的一致性的方式。

[*]在抽象的IEEE-754算术中是真的。在实际使用中,由于以扩展精度进行计算(MSVC,我正在看着你),一些编译器可能会在极少数情况下导致这种情况被违反。现在,英特尔架构上的大多数浮点计算都是在SSE而不是x87上完成的,这不是一个问题(无论如何,从IEEE-754的角度来看,它总是一个错误。)

答案 1 :(得分:3)

在Python中,当涉及NaN时,至少a>=b不等同于!(a<b)

>>> a = float('nan')
>>> b = 0
>>> a >= b
False
>>> not (a < b)
True

我想大多数其他语言也是如此。

另一件令你惊讶的事情是,NaN甚至没有与自己相提并论:

>>> a == a
False

答案 2 :(得分:3)

这组IEEE-754浮点数没有排序,因此您熟悉的某些关系和布尔代数不再成立。这种异常是由NaN引起的,NaN对于包含自身的集合中的任何其他值没有排序,因此所有关系运算符都返回false。这正是Mark Byers所展示的。

如果您排除NaN,那么您现在拥有一个有序集,并且您提供的表达式始终是等效的。这包括无穷大和负零。

答案 3 :(得分:2)

除了NaN问题,它有点类似于SQL中的NULL以及SAS和其他统计软件包中的缺失值,总是存在浮点算术精度的问题。重复小数部分中的值(例如,1/3)和无理数不能准确表示。由于精度的有限限制,浮点算术通常会截断结果。使用浮点值进行的算法越多,出现的错误就越大。

比较浮点值最有用的方法可能是算法:

  1. 如果任一值为NaN,则所有比较均为false,除非您明确检查NaN。
  2. 如果两个数字之间的差异在某个“模糊因子”内,则认为它们相等。模糊因子是您对累积数学不精确的容忍度。
  3. 模糊等式比较后,然后比较小于或大于。
  4. 请注意,比较“&lt; =”或“&gt; =”与精确相等的比较具有相同的风险。

答案 4 :(得分:1)

不,不是为了任何理智的浮点实现:基本对称和布尔逻辑适用。但是,equality in floating point numbers在其他方面很棘手。极少数情况下,对浮点数进行a==b测试是合理的。