Python からの出力で負のゼロが発生しました。たとえば、次のように作成されます。
k = 0.0
print(-k)
出力は になります-0.0
。
-k
ただし、等しいかどうかを 0.0と比較すると、 True が返されます。0.0
と の間に違いはありますか-0.0
(おそらく内部表現が異なることは気にしません。プログラム内での動作についてのみ気にします。) 知っておくべき隠されたトラップはありますか?
Python からの出力で負のゼロが発生しました。たとえば、次のように作成されます。
k = 0.0
print(-k)
出力は になります-0.0
。
-k
ただし、等しいかどうかを 0.0と比較すると、 True が返されます。0.0
と の間に違いはありますか-0.0
(おそらく内部表現が異なることは気にしません。プログラム内での動作についてのみ気にします。) 知っておくべき隠されたトラップはありますか?
基本的に、IEEE は実際には負のゼロを定義しています。
そして、この定義により、すべての目的のために:
-0.0 == +0.0 == 0
とが異なるオブジェクトであるというaaronasterlingに同意します。それらを等しくする (等値演算子) ことで、コードに微妙なバグが導入されないようにすることができます。
のことを考える-0.0
+0.0
a * b == c * d
>>> a = 3.4
>>> b =4.4
>>> c = -0.0
>>> d = +0.0
>>> a*c
-0.0
>>> b*d
0.0
>>> a*c == b*d
True
>>>
[編集:コメントに基づく詳細情報]
私がすべての実用的な目的のために言ったとき、私はかなり性急にその言葉を選びました。私は標準的な等値比較を意味していました。
参考文献にあるように、IEEE 標準では+0 = -0
、 ではなくとなるように比較を定義してい-0 < +0
ます。ゼロの符号を常に無視することは可能ですが、IEEE 標準ではそうしていません。乗算または除算に符号付きゼロが含まれる場合、通常の符号規則が答えの符号の計算に適用されます。
のような操作は、この動作divmod
をatan2
示します。実際、基礎となる「C」ライブラリと同様に、IEEE 定義にatan2
準拠しています。
>>> divmod(-0.0,100)
(-0.0, 0.0)
>>> divmod(+0.0,100)
(0.0, 0.0)
>>> math.atan2(0.0, 0.0) == math.atan2(-0.0, 0.0)
True
>>> math.atan2(0.0, -0.0) == math.atan2(-0.0, -0.0)
False
1 つの方法は、実装が IEEE の動作に準拠しているかどうかをドキュメントで確認することです。微妙なプラットフォームのバリエーションもあるという議論からも見えます。
ただし、この側面 (IEEE 定義への準拠) は、どこでも尊重されているわけではありません。無関心によるPEP 754の拒否を参照してください! これが後で拾われたかどうかはわかりません。
What Every Computer Scientist Should Know About Floating-Point Arithmeticも参照してください。
math.copysign()
変なプラットフォームで Python を実行している場合を除き、-0.0
と を異なる方法で扱います。+0.0
math.
copysign ( x , y ) yの符号を持つx
を 返します。符号付きゼロをサポートするプラットフォームでは、 を返します。copysign(1.0, -0.0)
-1.0
>>> import math
>>> math.copysign(1, -0.0)
-1.0
>>> math.copysign(1, 0.0)
1.0
それはatan2()
機能に違いをもたらします(少なくとも、いくつかの実装では)。私の Windows 上の Python 3.1 および 3.2 では (Pythonモジュールのドキュメントの下部にあるメモCPython 実装の詳細によると、基になる C 実装に基づいています):math
>>> import math
>>> math.atan2(0.0, 0.0)
0.0
>>> math.atan2(-0.0, 0.0)
-0.0
>>> math.atan2(0.0, -0.0)
3.141592653589793
>>> math.atan2(-0.0, -0.0)
-3.141592653589793
はい、0.0 と -0.0 には違いがあります (ただし、Python では再現できません:-P)。正の数を 0.0 で割ると、正の無限大になります。同じ数を -0.0 で割ると、負の無限大になります。
ただし、それ以上は、2 つの値の間に実質的な違いはありません。