【问题标题】:Wrong value for cube root in PythonPython中立方根的错误值
【发布时间】:2017-02-12 15:27:26
【问题描述】:

repl.it 和 Windows 中的控制台上使用 Python 3.5,我得到了关于立方根的错误答案。

当输入为(-1)**(1/3)时, 当它应该只是-1时,我得到复数(0.5000000000000001+0.8660254037844386j)作为答案。此根下的任何负值似乎都会给出复杂的结果。

我做错了吗?

【问题讨论】:

标签: python math


【解决方案1】:

负底的求幂通常涉及复数,因此 Python 在看到负底时会切换到复数。这种求幂通常是多值的,Python 并不总是返回您可能期望的值。

对于实底的 1/3 幂的特殊情况,您可以编写如下函数:

def cubeRoot(x):
    if x >= 0:
        return x**(1/3)
    else:
        return -(-x)**(1/3)

这将给出预期的真实立方根。

【讨论】:

  • 在对此进行了更多研究之后,我似乎无法找到一种在这种情况下将所有 3 都归还给你的方法,只是能够像你在这个答案中那样强制实数。不知道有没有这样的方法?
  • 例如,我从here尝试了两种方法,真实的root被报告为-1+1.2246467991473532e-16j。这只是出于我自己的好奇心,不是 OP 要求的。
  • 1/3 不能表示为浮点数,因此 (-1)**x 的值超过 3 个,其中 x 是最接近 1/3 的浮点数。
  • @PaulHankin 我理解浮点限制,但在这种特殊情况下,有一个真正的根。但即便如此,我尝试过的那些也有一个虚构的部分(尽管非常小)被报告回来。
  • @roganjosh 好问题。不知道我的头顶。 sympy 中的某些内容可能会起作用,例如 sympy.roots
【解决方案2】:

实际上,Python 并不知道你在取立方根!

它看到的只是一个浮点参数,其值接近 0.3333333333...,但由于表示的有限性,无法猜测您的意思是 1/3。

因此,Python 所能做的就是通过公式将负基的幂运算(主分支)回归到通常的定义中

(-x)^y = exp(y(ln(x) + iπ) = exp(y ln(x)) (cos(yπ) + i sin(yπ))

产生一个复数。

【讨论】:

    【解决方案3】:

    你会得到这个答案,因为幂算子会计算

    x**y = exp(y*ln(x))
    

    如果x 不是一个正实数,那么它的对数是从复数对数的主分支计算出来的

    ln(u+i*v)=0.5*ln(u²+v²) + i*arg(u+i*v)
    

    在数学库术语中的位置arg(u+i*v)=atan2(v,u)

    因此ln(-1)=i*pi

    (-1)**(1.0/3)=exp(i*pi/3)=cos(pi/3)+i*sin(pi/3)
    

    它具有您获得的价值。浮点错误发生是因为y=1.0/3 不完全是1/3pi 不完全是同名的数学常数,并且三角函数也是精确数学函数的近似值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      • 2011-05-18
      • 1970-01-01
      相关资源
      最近更新 更多