21

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

Prelude> abs (-0.0)
-0.0

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

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

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

4

3 回答 3

14

您描述的行为绝对与 IEEE 754 标准不一致,该标准在其最新版本中说:

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

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

除非 Haskell 明确声称遵循 IEEE 754 标准,否则这不会使其成为 Haskell 中的错误,并且还声称absPrelude 中的实现应该映射到 IEEE 754abs函数。该标准仅要求abs必须提供操作,但没有说明它的拼写方式。

于 2012-05-01T18:09:23.707 回答
7

这是Haskell 报告中定义的行为。

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

于 2012-05-01T09:57:02.903 回答
4

正如 IEEE 标准所说0 == (-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一旦我能找到一些关于应该如何实例化的参考资料,我会尽快写一篇更新。

于 2012-05-01T09:46:07.810 回答