[Tutor] Little problem with math module

Terry Carroll carroll at tjc.com
Wed May 21 10:25:22 CEST 2008


> "Tiago Katcipis" <katcipis at inf.ufsc.br> wrote 
> 
> > def newton_divergente(x): 
> >  return math.pow(x, 1.0/3.0)
> > 
> > but when x = -20 it returns this error
> > 
> > return math.pow(x, 1.0/3.0)
> > ValueError: math domain error
> > 
> > but why is that? is it impossible to calculate -20 ^ (1/3) ?

Can I chime in late on this one?  I'm catching up on some old email.

It's already been pointed out that a negative number cannot be raised to a
fractional power.  But as long as you're only looking to calculate roots
you should be able to calculate them unless the number is negative *and*
the root is even. For example, you cannot (without getting into complex
numbers) take the square root (an even root) of -8.  But the cube root (an 
odd root) of -8 is -2.

N**1/x is equal to -(-N**1/x), as long as the constraints above are 
met.  Relying on this, you can easily write an "nthroot" routine that 
calculates the non-complex nth root of a number, unless the number is 
negative and the root-number is even:

def nthroot(x, n):
    """returns the non-complex nth root of x"""
    if x > 0:
        return x**(1.0/n)
    elif n%2 == 1:
        return -(-x)**(1.0/n)
    else:
        raise ValueError, "even root cannot be calculated for negative number"

For example:

>>> nthroot(100, 2)
10.0
>>> nthroot(8, 3)
2.0
>>> nthroot(-8, 3)
-2.0
>>> nthroot(-8, 2)  # this is a no-no; negative number & even root
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "nthroots.py", line 8, in nthroot
    raise ValueError, "even root cannot be calculated for negative number"
ValueError: even root cannot be calculated for negative number
>>>

Now, if you *are* willing to get into complex numbers, i.e., numbers with 
an imaginary component, you should be aware that there's no such thing as 
*the* Nth root of a number.  Instead there are N Nth roots, evenly spaced 
in a circle centered on 0+0i.

For example, the number 16 has two square roots, at 4 and -4; or more
completely 4+0i and -4+0i.

But it has 4 4th roots.  Obviously it has 2 and -2 (2+0i and -2+0i); but 
it also has 0+2i and 0-2i:

   (0+2i)*(0+2i)*(0+2i)*(0+2i) = -4 * -4 = 16
   (0-2i)*(0-2i)*(0-2i)*(0-2i) =  4 *  4 = 16

The following (barely-tested) routine should calculate all the Nth roots
of a given x, even when x is negative and N is even:

def nthroots(x, n):
    """returns a list of all nth roots of x"""
    from math import pi, cos, sin
    roots = []
    if x >=1:
        startangle = 0
    else:
        startangle = pi/2
    firstroot = abs(x)**(1.0/n)
    for i in range(0, n):
        angle = (i*(2*pi)/n)+startangle
        root = complex(firstroot*cos(angle), firstroot*sin(angle))
        roots.append(root)
    return roots

Example:

>>> nthroots(16,4)
[(2+0j), (1.2246063538223773e-016+2j), (-2+2.4492127076447545e-016j), 
(-3.6738190614671318e-016-2j)]

Apart from precision issues, those are 2+0j, 0+2j, -2+0j and 0-2j.



More information about the Tutor mailing list