我知道有符号的零用于区分下溢与正数或负数,因此值得区分它们。直观地,我觉得-0.0
的绝对值应该是0.0
。但是,这不是Haskell所说的:
Prelude> abs (-0.0)
-0.0
对于它的价值,Python 2.7不同意:
>>> -0.0
-0.0
>>> abs(-0.0)
0.0
这是一个错误,还是标准的一部分?
答案 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幅度与标志
数字具有幅度和符号。函数
abs
和signum
适用于任何数字并符合法律: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 says,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
实例化的参考资料后立即撰写更新。