负零的绝对值 - bug,还是浮点标准的一部分?

时间:2012-05-01 09:19:45

标签: haskell floating-point

我知道有符号的零用于区分下溢与正数或负数,因此值得区分它们。直观地,我觉得-0.0的绝对值应该是0.0。但是,这不是Haskell所说的:

Prelude> abs (-0.0)
-0.0

对于它的价值,Python 2.7不同意:

>>> -0.0
-0.0
>>> abs(-0.0)
0.0

这是一个错误,还是标准的一部分?

3 个答案:

答案 0 :(得分:12)

您描述的行为肯定与IEEE 754标准不一致,后者在最近的版本中说:

  

abs(x)将浮点操作数x复制到目标中   格式,将符号位设置为0(正)。

这是在IEEE 754-2008的第5.5.1节中,标题为“符号位操作”。虽然我无法提供标准本身的链接,但您可以在7.5.1节中看到标准的最后一个public draft大致相同的语言。 (一般来说,标准与草案的区别很大,但这一点几乎没有变化。)

除非Haskell明确声称遵循IEEE 754标准,否则这不会成为Haskell中的错误,而且声称Prelude中abs的实现应映射到IEEE 754 abs功能。该标准仅要求必须提供abs操作,但不说明如何拼写。

答案 1 :(得分:7)

这是Haskell report中定义的行为。

  

6.4.4幅度与标志

     

数字具有幅度符号。函数abssignum适用于任何数字并符合法律:

abs x * signum x == x
     

对于实数,这些函数由以下定义:

abs x    | x >= 0  = x  
         | x <  0  = -x  

signum x | x >  0  = 1  
         | x == 0  = 0  
         | x <  0  = -1

由于负零等于零,-0.0 >= 0为真,所以abs (-0.0) = -0.0。这也与signum的定义一致-0.0 * 0.0 = -0.0

答案 2 :(得分:4)

As the IEEE standard says0 == (-0)即使他们有不同的迹象。这是非常合理的,没有什么是你用的任何标志。这意味着

let nzero = (-0.0)
    a = abs nzero
in a == 0.0 && a == nzero

评估为True,因为事实上,无论abs x == 0还是abs x == (-0)都是一样的。虽然这是一个值得怀疑的选择,但我觉得abs (-0.0) == (-0.0)对我来说不是一个错误。

修改: 正如评论所指出的那样,show 0.0 /= show (-0.0)。我不确定如何证明这一点。我此刻想到的唯一一件事是,Eq可能并不代表与参照透明度有关的约束合同,例如一个类型的两个值实际上不必以相同的方式表示以被视为等同。

我会在找到有关如何Eq实例化的参考资料后立即撰写更新。