Why is (-27)**(1.0/3.0) not -3.0 in Python?

前端 未结 3 2016
耶瑟儿~
耶瑟儿~ 2020-12-21 01:46

In math, you are allowed to take cubic roots of negative numbers, because a negative number multiplied by two other negative numbers results in a negative number. Raising so

相关标签:
3条回答
  • 2020-12-21 02:22

    The type coercion rules documented by builtin pow apply here, since you're using a float for the exponent.

    Just make sure that either the base or the exponent is a complex instance and it works:

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

    To find all three roots, consider numpy:

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

    The list [1, 0, 0, 27] here refers to the coefficients of the equation 1x³ + 0x² + 0x + 27.

    0 讨论(0)
  • 2020-12-21 02:33

    -27 has a real cube root (and two non-real cube roots), but (-27)**(1.0/3.0) does not mean "take the real cube root of -27".

    First, 1.0/3.0 doesn't evaluate to exactly one third, due to the limits of floating-point representation. It evaluates to exactly

    0.333333333333333314829616256247390992939472198486328125
    

    though by default, Python won't print the exact value.

    Second, ** is not a root-finding operation, whether real roots or principal roots or some other choice. It is the exponentiation operator. General exponentiation of negative numbers to arbitrary real powers is messy, and the usual definitions don't match with real nth roots; for example, the usual definition of (-27)^(1/3) would give you the principal root, a complex number, not -3.

    Python 2 decides that it's probably better to raise an error for stuff like this unless you make your intentions explicit, for example by exponentiating the absolute value and then applying the sign:

    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)
    

    or by using complex exp and log to take the principal root:

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

    or by just casting to complex for complex exponentiation (equivalent to the exp-log thing up to rounding error):

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

    Python 3 uses complex exponentiation for negative-number-to-noninteger, which gives the principal nth root for y == 1.0/n:

    >>> (-27)**(1/3)  # Python 3
    (1.5000000000000004+2.598076211353316j)
    
    0 讨论(0)
  • 2020-12-21 02:44

    I do not think Python, or your version of it, supports this function. I pasted the same equation into my Python interpreter, (IDLE) and it solved it, with no errors. I am using Python 3.2.

    0 讨论(0)
提交回复
热议问题