【问题标题】:Why is (-27)**(1.0/3.0) not -3.0 in Python?为什么 (-27)**(1.0/3.0) 在 Python 中不是 -3.0?
【发布时间】:2018-04-07 10:19:35
【问题描述】:

在数学中,您可以取负数的立方根,因为负数乘以其他两个负数会得到一个负数。将某事物提高到分数幂 1/n 与取它的 n 次方相同。因此,-27 或 (-27)**(1.0/3.0) 的三次根为 -3。

但是在 Python 2 中,当我输入 (-27)**(1.0/3.0) 时,它给了我一个错误:

Traceback (most recent call last):
  File "python", line 1, in <module>
ValueError: negative number cannot be raised to a fractional power

Python 3 不会产生异常,但它会给出一个看起来不像 -3 的复数:

>>> (-27)**(1.0/3.0)
(1.5000000000000004+2.598076211353316j)

为什么我没有得到具有数学意义的结果?有没有解决方法?

【问题讨论】:

  • 重新打开。我认为这些欺骗目标都不合适。一个没有解释,另一个在谈论不同的问题。这个问题需要解释。
  • 问题是1.0/3.0 不是分数而是浮点数。
  • 有关所有问题的更好解释,请参阅:stackoverflow.com/q/31231115/984421

标签: python


【解决方案1】:

-27 有一个实数立方根(和两个非实数立方根),但(-27)**(1.0/3.0) 并不表示“取-27 的实数立方根”。

首先,由于浮点表示的限制,1.0/3.0 不会精确到三分之一。它的计算结果是准确的

0.333333333333333314829616256247390992939472198486328125

虽然默认情况下,Python 不会打印确切的值。

其次,** 不是寻根操作,无论是真根还是主根或其他选择。它是幂运算符。负数对任意实幂的一般取幂是混乱的,通常的定义与实数 n 次根不匹配;例如,(-27)^(1/3) 的通常定义会给你主根,一个复数,而不是 -3。

Python 2 认为最好为这样的东西引发错误,除非你明确表示你的意图,例如通过对绝对值求幂然后应用符号:

def real_nth_root(x, n):
    # approximate
    # if n is even, x must be non-negative, and we'll pick the non-negative root.
    if n % 2 == 0 and x < 0:
        raise ValueError("No real root.")
    return (abs(x) ** (1.0/n)) * (-1 if x < 0 else 1)

或使用复杂的explog 来获取主根:

import cmath
def principal_nth_root(x, n):
    # still approximate
    return cmath.exp(cmath.log(x)/n)

或者通过转换为 complex 进行复幂运算(相当于 exp-log 的东西直到舍入错误):

>>> complex(-27)**(1.0/3.0)
(1.5000000000000004+2.598076211353316j)

Python 3 对负数到非整数使用复幂运算,这为 y == 1.0/n 提供了主体 nth 根:

>>> (-27)**(1/3)  # Python 3
(1.5000000000000004+2.598076211353316j)

【讨论】:

  • @EricDuminil:确实,最好检查是否存在真正的根,而不是假设它。我添加了一张支票。
  • 不错。这个答案现在是我能在 SO 上找到的最好的答案!
【解决方案2】:

内置 powtype coercion rules documented 在这里适用,因为您使用浮点数作为指数。

只要确保基数或指数是一个复杂的实例并且它可以工作:

>>> (-27+0j)**(1.0/3.0)
(1.5000000000000004+2.598076211353316j)
>>> (-27)**(complex(1.0/3.0))
(1.5000000000000004+2.598076211353316j)

要找到所有三个根,请考虑numpy

>>> import numpy as np
>>> np.roots([1, 0, 0, 27])
array([-3.0+0.j        ,  1.5+2.59807621j,  1.5-2.59807621j])

这里的列表[1, 0, 0, 27]指的是方程1x³+0x²+0x+27的系数

【讨论】:

    【解决方案3】:

    我认为 Python 或您的版本不支持此功能。我将相同的方程式粘贴到我的 Python 解释器 (IDLE) 中,它解决了它,没有错误。我正在使用 Python 3.2。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      相关资源
      最近更新 更多