【问题标题】:negative zero in pythonpython中的负零
【发布时间】:2011-05-04 06:15:53
【问题描述】:

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

k = 0.0
print(-k)

输出将是-0.0

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

【问题讨论】:

  • python 2.5.4 不会给出负值
  • 真正隐藏的陷阱是当您开始测试浮点值是否相等时。它们不精确并且容易出现奇怪的四舍五入差异。
  • 但它确实在 Python 2.7.1 上打印负值。
  • 这个问题出现在现实生活中的gps应用程序中;子午线稍偏西的经度被报告为 0 度 x 分,而它本应为负零度 x 分。但是python不能表示整数负零。

标签: python floating-point floating-accuracy zero


【解决方案1】:

是的,0.0 和 -0.0 之间存在差异(尽管 Python 不会让我重现它:-P)。如果将正数除以 0.0,则得到正无穷大;如果将相同的数字除以 -0.0,则会得到负无穷大。

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

【讨论】:

  • 你不能除以 0。如果你说的是极限,-0 就更没有意义了。
  • -1 你不能除数 0 因为你得到一个 ZeroDivisonError。这意味着没有区别。
  • @Falmarri:在 Python 中,你不能;在其他语言中,你很好。我在处理一般浮点处理意义上的 0.0 和 -0.0 之间的区别。
  • +1 取消反对票。 Chris 是正确的,例如,在 C 中,浮点除以 0.0 被定义为产生具有符号的无穷大(分子和分母具有相同的符号)?正面:负面。
  • @DMan:重要的是(a)它们存在并且(b)有一个实现。 (即使它是部分的。)因为你(和我)没有看到复杂的数学细节并没有任何意义。它们仍然存在。我不懂偏微分方程,看不到实用价值。有些人会。我认为该标准的实用价值有限。那不是重点。我对“实用”的拙见没有任何价值。它仍然存在,它仍然具有意义,并且仍然部分实现。
【解决方案2】:

查看−0 (number) in Wikipedia

基本上 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
>>> 

[编辑:基于 cmets 的更多信息]

当我出于所有实际目的说这个词时,我是相当仓促地选择了这个词。我的意思是标准的平等比较。

正如参考资料所说,IEEE 标准定义了比较,以便+0 = -0,而不是-0 < +0。尽管总是可以忽略零的符号,但 IEEE 标准并没有这样做。当乘法或除法涉及带符号的零时,通常的符号规则适用于计算答案的符号。

divmodatan2 之类的操作会表现出这种行为。事实上,atan2complies 与 IEEE 定义一样,底层的“C”库也是如此。

>>> 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因不感兴趣而被拒绝!我不确定这是不是后来被捡到的。

另见What Every Computer Scientist Should Know About Floating-Point Arithmetic

【讨论】:

  • @aaronasterling:你为什么删除你的答案?这是对这里信息的宝贵补充。我刚投了赞成票。
  • 因为我对它的最后一部分有误,而其余部分并不是我的帖子所独有的。
  • 如果它“在所有方面都相等”,它如何解释 Craig McQueen 的回答中 atan2 的差异?我同意它在比较相等时返回 True,但如果这两个数字的行为可能会有所不同,我想知道何时。
  • @max 请注意,反正切函数基本上是在寻找所提供参数的斜率(和方向),因此在内部它被零除导致不连续性,这不足为奇。此外,函数输出是循环的,周期为 2π,+π 和 -π 是“相同的”。
【解决方案3】:

它在atan2() 函数中有所不同(至少,在某些实现中)。在我在 Windows 上的 Python 3.1 和 3.2 中(它基于底层 C 实现,根据 bottom of the Python math module documentation 附近的注释 CPython 实现细节):

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

【讨论】:

    【解决方案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

    【讨论】:

      【解决方案5】:

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

      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
      

      【讨论】:

      • numpy 也有一个copysign。耶!
      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 2012-07-05
        • 2016-08-25
        • 2011-03-09
        • 2012-08-24
        • 1970-01-01
        • 2015-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多