Python 中的负零

negative zero in python

提问人:max 提问时间:11/3/2010 最后编辑:wjandreamax 更新时间:11/10/2022 访问量:49215

问:

我在 python 的输出中遇到了负零;例如,它的创建方式如下:

k = 0.0
print(-k)

输出将为 。-0.0

但是,当我将相等性与 0.0 进行比较时,它会产生 True。和之间有什么区别吗(我不在乎它们可能有不同的内部表示;我只关心他们在程序中的行为。有什么隐藏的陷阱是我应该注意的吗?-k0.0-0.0

Python 浮点 精度 为零

评论

0赞 Ankit Jaiswal 11/3/2010
python 2.5.4 不会给出负值
1赞 Sean McSomething 11/4/2010
真正隐藏的陷阱是当你开始测试浮点值的相等性时。它们不准确,容易出现奇怪的四舍五入差异。
0赞 syntagma 3/5/2013
但它确实在 Python 2.7.1 上打印负值。
3赞 secret squirrel 9/1/2016
这个问题出现在现实生活中的 gps 应用程序中;子午线稍偏西的经度被报告为零度和 x 分钟,而它应该是负零度和 x 分钟。但是 python 不能表示整数负零。

答:

15赞 C. K. Young 11/3/2010 #1

是的,0.0 和 -0.0 之间是有区别的(尽管 Python 不允许我重现它:-P)。如果将正数除以 0.0,则得到正无穷大;如果将相同的数字除以 -0.0,则得到负无穷大。

但是,除此之外,这两个值之间没有实际区别。

评论

4赞 Falmarri 11/3/2010
你不能除以 0。如果你说的是极限,-0 就更没有意义了。
4赞 Dominic K 11/3/2010
-1 你不能将数字 0 除以,因为你得到一个 ZeroDivisonError。这意味着没有区别。
11赞 C. K. Young 11/3/2010
@Falmarri:在 Python 中,你不能;在其他语言中,你完全可以。我正在解决一般浮点处理意义上的 0.0 和 -0.0 之间的区别。
7赞 AlcubierreDrive 11/3/2010
+1 抵消反对票。Chris是正确的,例如,在C中,浮点除以0.0被定义为产生带有符号的无穷大(分子和分母具有相同的符号)?positive :消极。
4赞 S.Lott 11/5/2010
@DMan:重要的是(a)它们存在,(b)有一个实现。(即使它是部分的。因为你(和我)没有看到复杂的数学微妙之处并不意味着什么。它们仍然存在。我不懂偏微分方程,看不出有什么实用价值。有些人会这样做。我认为该标准的实际价值有限。这不是重点。我对“实用”的拙见是没有道理的。它仍然存在,它仍然有意义,并且仍然部分实现。
49赞 pyfunc 11/3/2010 #2

维基百科中查看−0(数字)

基本上,IEEE实际上定义了负零。

根据这个定义,出于所有目的:

-0.0 == +0.0 == 0

我同意aaronasterling的观点,并且是不同的对象。使它们相等(相等运算符)可确保代码中不会引入细微的错误。
-0.0+0.0a * 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标准定义了比较,因此,而不是.尽管可以始终忽略零符号,但IEEE标准不会这样做。当乘法或除法涉及有符号的零时,通常的符号规则适用于计算答案的符号。+0 = -0-0 < +0

操作喜欢并表现出此行为。事实上,它符合IEEE的定义,底层的“C”库也是如此。divmodatan2atan2

>>> 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

一种方法是通过文档找出实现是否符合IEEE行为。从讨论中似乎也存在微妙的平台变化。

然而,这方面(IEEE定义合规性)并未在任何地方得到尊重。看到 PEP 754 因不感兴趣而被拒绝!我不确定这是否是后来发现的。

另请参阅每个计算机科学家都应该了解的有关浮点运算的知识

评论

0赞 pyfunc 11/3/2010
@aaronasterling:你为什么删除你的答案?这是对这里信息的宝贵补充。我只是给它投了赞成票。
0赞 aaronasterling 11/3/2010
因为我对它的最后一部分是错误的,而其余部分并不是我的帖子所独有的。
0赞 max 11/4/2010
如果它是“所有目的都是平等的”,它如何解释克雷格·麦昆(Craig McQueen)答案中的差异?我同意在比较相等性时它返回 True,但如果两个数字的行为可能有所不同,我想知道什么时候。atan2
0赞 Nick T 3/11/2014
@max 请注意,反正切函数基本上是在寻找所提供参数的斜率(和方向),因此在内部它除以零,导致不连续性,这不足为奇。此外,函数输出是周期为 2π、+π 和 -π 的循环输出是“相同的”。
18赞 Craig McQueen 11/3/2010 #3

它在 atan2() 函数中有所作为(至少在某些实现中是这样)。在 Windows 上的 Python 3.1 和 3.2 中(根据Python math 模块文档底部附近的注释 CPython 实现详细信息,它基于底层 C 实现):

>>> 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
1赞 user 3/14/2014 #4

相同的值,但不同的数字

>>> Decimal('0').compare(Decimal('-0'))        # Compare value
Decimal('0')                                   # Represents equality

>>> Decimal('0').compare_total(Decimal('-0'))  # Compare using abstract representation
Decimal('1')                                   # Represents a > b

参考资料 :
http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare_total

22赞 Alex Trebek 8/16/2014 #5

math.copysign() 以不同的方式处理,除非您在奇怪的平台上运行 Python:-0.0+0.0

math.copysignxy)
返回带 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

评论

0赞 The Unfun Cat 6/18/2018
numpy 也有一个 copysign。耶!
0赞 Samuel Châtelain-lacasse 11/14/2021 #6

为了概括或总结其他答案,实践中的差异似乎来自计算在 0 处停止的函数,其中不连续性来自 0 除法。然而,python 将 0 除法定义为错误。因此,如果使用 python 运算符计算任何内容,您可以简单地 将 -0.0 视为 +0.0,无需担心。相反,如果函数是由内置函数或用另一种语言(如 C)编写的库计算的,则 0 除法可以在该语言中以其他方式定义,并且可能会给出 -0.0 和 0.0 的不同答案。

2赞 bfree67 11/10/2022 #7

如果您担心遇到 -0.0 的情况,只需添加 + 0。到等式。它不会影响结果,但会强制零为正浮点数。

import math

math.atan2(-0.0, 0.0)
Out[2]: -0.0

math.atan2(-0.0, 0.0) + 0.
Out[3]: 0.0