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標準と完全に矛盾しています。IEEE 754標準は、最新の化身で次のように述べています。

abs(x) は、浮動小数点オペランド x を同じ形式でコピー先にコピーし、符号ビットを 0 (正) に設定します。

これは、IEEE 754-2008 のセクション 5.5.1 の「Sign bit operations」にあります。標準自体へのリンクを提供することはできませんが、セクション 7.5.1 で、標準の最新のパブリック ドラフトでほぼ同じ言語を見ることができます。(一般に、標準はそのドラフトとはかなり異なりますが、このビットはほとんど変更されていません。)

Haskell が特に IEEE 754 標準に従うと主張し、さらにabsPrelude での実装が IEEE 754abs関数にマップされるべきであると主張しない限り、それは Haskell のバグにはなりません。標準では、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 == 0abs x == (-0)abs (-0.0) == (-0.0)

編集:コメントが指摘するように、show 0.0 /= show (-0.0). これを正当化する方法がわかりません。現時点で私の頭に浮かんだ唯一のことは、おそらく、Eq参照の透過性に関する境界契約を表していないということです。 .

Eqインスタンス化する方法についての参考文献が見つかり次第、更新を書きます。

于 2012-05-01T09:46:07.810 に答える