python 中的负零
我在 python 的输出中遇到了负零;例如,它的创建如下:
k = 0.0
print(-k)
输出将为-0.0
。
但是,当我将 -k
与 0.0 进行比较时,结果为 True。 0.0
和 -0.0
之间有什么区别吗(我不关心它们可能有不同的内部表示;我只关心它们在程序中的行为。)我应该注意哪些隐藏的陷阱?
I encountered negative zero in output from python; it's created for example as follows:
k = 0.0
print(-k)
The output will be -0.0
.
However, when I compare the -k
to 0.0 for equality, it yields True. Is there any difference between 0.0
and -0.0
(I don't care that they presumably have different internal representation; I only care about their behavior in a program.) Is there any hidden traps I should be aware of?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
查看维基百科中的 −0(数字)
基本上 IEEE 是这样做的实际上定义了一个负零。
根据这个定义,无论出于何种目的:
我同意 aaronasterling 认为
-0.0
和+0.0
是不同的对象。使它们相等(相等运算符)可确保代码中不会引入细微的错误。想想
a * b == c * d
[编辑:基于评论的更多信息]
当我说出于所有实际目的时,我相当仓促地选择了这个词。我的意思是标准平等比较。
正如参考文献所述,IEEE 标准定义了比较,以便
+0 = -0
,而不是-0
+0
。尽管始终可以忽略零符号,但 IEEE 标准并没有这样做。当乘法或除法涉及有符号零时,通常的符号规则适用于计算答案的符号。divmod
和atan2
等操作就表现出这种行为。事实上,atan2
符合 IEEE 定义,底层“ C”库。一种方法是通过文档查明该实现是否符合 IEEE 行为。从讨论中还可以看出,平台也存在微妙的差异。
然而,这方面(IEEE 定义合规性)并没有在所有地方得到尊重。请参阅由于不感兴趣而拒绝 PEP 754!我不确定这是不是后来才发现的。
另请参阅每个计算机科学家应该了解的浮点运算知识。
Check out −0 (number) in Wikipedia
Basically IEEE does actually define a negative zero.
And by this definition for all purposes:
I agree with aaronasterling that
-0.0
and+0.0
are different objects. Making them equal (equality operator) makes sure that subtle bugs are not introduced in the code.Think of
a * b == c * d
[Edit: More info based on comments]
When I said for all practical purposes, I had chosen the word rather hastily. I meant standard equality comparison.
As the reference says, the IEEE standard defines comparison so that
+0 = -0
, rather than-0 < +0
. Although it would be possible always to ignore the sign of zero, the IEEE standard does not do so. When a multiplication or division involves a signed zero, the usual sign rules apply in computing the sign of the answer.Operations like
divmod
andatan2
exhibit this behavior. In fact,atan2
complies with the IEEE definition as does the underlying "C" lib.One way is to find out through the documentation, if the implementation complies with IEEE behavior . It also seems from the discussion that there are subtle platform variations too.
However this aspect (IEEE definition compliance) has not been respected everywhere. See the rejection of PEP 754 due to disinterest! I am not sure if this was picked up later.
See also What Every Computer Scientist Should Know About Floating-Point Arithmetic.
math.copysign()
对待-0.0
和+0.0
不同,除非你在奇怪的平台上运行 Python:math.copysign()
treats-0.0
and+0.0
differently, unless you are running Python on a weird platform:它在
atan2()
< /a> 函数(至少在某些实现中)。在我的 Windows 上的 Python 3.1 和 3.2 中(基于底层 C 实现,根据 Pythonmath
模块文档底部):It makes a difference in the
atan2()
function (at least, in some implementations). In my Python 3.1 and 3.2 on Windows (which is based on the underlying C implementation, according to the note CPython implementation detail near the bottom of the Pythonmath
module documentation):是的,0.0 和 -0.0 之间是有区别的(尽管 Python 不允许我重现它:-P)。如果将正数除以 0.0,则会得到正无穷大;如果将相同的数字除以 -0.0,则会得到负无穷大。
但除此之外,这两个值之间没有实际差异。
Yes, there is a difference between 0.0 and -0.0 (though Python won't let me reproduce it :-P). If you divide a positive number by 0.0, you get positive infinity; if you divide that same number by -0.0 you get negative infinity.
Beyond that, though, there is no practical difference between the two values.
如果您担心遇到 -0.0 的情况,只需在方程中添加 + 0. 即可。它不会影响结果,但会强制零点变为正浮点数。
If you are ever concerned about running into a -0.0 condition, just add + 0. to the equation. It does not influence the results but forces the zeros to a positive float.
相同的值,但不同的数字
参考:
http://docs.python.org/2/library/decimal .html#decimal.Decimal.compare
http://docs.python.org/2/library/decimal .html#decimal.Decimal.compare_total
Same values, yet different numbers
Reference :
http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare
http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare_total
为了概括或总结其他答案,实践中的差异似乎来自计算在 0 处中断的函数,其中不连续性来自 0 除法。然而,Python 将 0 除法定义为错误。因此,如果使用 python 运算符计算任何内容,您可以简单地
将 -0.0 视为 +0.0,无需担心。相反,如果该函数是由内置函数或用另一种语言(例如 C)编写的库计算的,则 0 除法可能会在该语言中以其他方式定义,并且可能会给出 -0.0 和 0.0 的不同答案。
To generalise or summarise the other answers, the difference in practice seems to come from calculating functions that are discontinued at 0 where the discontinuity is coming from a 0 division. Yet, python defines a 0 division as an error. So if anything is calculated with python operators, you can simply
consider -0.0 as +0.0 and nothing to worry from. On the contrary, if the function is calculated by a built in function or a library that is written in another language, such as C, the 0 division may be defined otherwise in that language and may give different answers for -0.0 and 0.0.
Python 浮点数是标准浮点数,但某些操作会在更高级别上捕获并引发
ZeroDivisionError
或OverflowError
。因此,在纯 Python 中,您看不到正零和负零之间可以说是最显着的区别,即:在标准浮点算术中,您有 1/(−0) = −∞ ≠ ∞ = 1/0。但是,库可以删除这些捕获,并在默认情况下不受限制地使用浮点运算。这尤其包括 NumPy,它又被许多其他库在幕后使用。这些库可以按原样使用 Python 浮点数,保留零的符号。在这种情况下,负零和正零之间可能会出现明显的差异,例如:
在复杂的数值例程中偶尔会出现这种行为的实际需要。例如,当通过复杂的试验和错误寻找函数的最小值时,错误的猜测可能会导致数值上溢或下溢,但只要所得的无穷大带有正确的符号,极小化器就可以继续工作,而无需废话不多说(拒绝猜测)。我在这个答案中给出了详细的示例。
Python floats are standard floating-point numbers, except that certain actions are caught on a higher level and raise
ZeroDivisionError
orOverflowError
. Therefore, in pure Python, you cannot see the arguably most prominent difference between positive and negative zero, namely: In standard floating-point arithmetics, you have 1/(−0) = −∞ ≠ ∞ = 1/0.However, libraries can remove these catches, and use floating-point arithmetics without restrictions by default. This particularly includes NumPy, which in turn is used by many other libraries under the hood. These libraries can use Python floats as they are, preserving the sign of zero. In this case, clear differences between negative zero and positive zero can arise, for example:
The practical need for such a behaviour occasionally arises in complex numerical routines. For example when looking for the minimum of a function with sophisticated trial and error, a bad guess may lead to a numerical over- or underflow, but as long as the resulting infinity comes along with the correct sign, the minimiser can continue to work without further ado (rejecting the guess). I give a detailed example for this in this answer.