Python program to implement pow(x, n) This is a Leetcode problem:


  Implement pow(x, n), which calculates x raised to the power n (\$x^n\$).
  
  Note -
  
  
  -100.0 &lt; x &lt; 100.0
  n is a 32-bit signed integer, within the range [\$-2^{31}\$, \$2^{31}\$ − 1]
  


def pow(x, n):
    if n == 0:
        return 1
    if x == 0 and n &lt; 0:
        return
    result = 1
    if n &gt; 0:
        while n &gt; 0:
            pre_result = result
            result *= x
            if pre_result == result or pre_result == -result:
                if result &gt;= 0:
                    return result
                if n % 2 == 0:
                    return -result
                else:
                    return result
            n -= 1
        return result
    else:
        while n &lt; 0:
            pre_result = result
            result /= x
            if pre_result == result or pre_result == -result:
                if result &gt;= 0:
                    return result
                if n % 2 == 0:
                    return -result
                else:
                    return result
            n += 1
        return result


NOTE - My solution is \$O(n)\$.

Here are some example inputs/outputs:

#print(pow(2.00000, 10))

&gt;&gt;&gt; 1024.0

#print(pow(2.10000, 3))

&gt;&gt;&gt; 9.261

#print(pow(2.00000, -2))

&gt;&gt;&gt; 0.25

#print(pow(-1.00000, -2147483648))

&gt;&gt;&gt; 1.0


Here are the times taken for each output:

#%timeit pow(2.00000, 10)

&gt;&gt;&gt; 1.88 µs ± 14 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

#%timeit pow(2.10000, 3)

&gt;&gt;&gt; 805 ns ± 17.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

#%timeit pow(2.00000, -2)

&gt;&gt;&gt; 643 ns ± 9.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

#%timeit pow(-1.00000, -2147483648)

&gt;&gt;&gt; 594 ns ± 20 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)


So, I would like to know whether I could make this program shorter and more efficient.

Any help would be highly appreciated.
Do less writing

You can half the code by using the fact \$x^{-n} = \frac{1}{x^n}\$

if n &gt; 0:
    while n &gt; 0:
    ...
else:
    while n &lt; 0:
    ...


would become

if n &lt; 0:
    # x**(-n) == 1 / x**n
    return 1 / old_code(x, -n)

return old_code(x, n)


(with old code being the code you have from the while loop down)



Likewise \$(-x)^n = x^n\$ if n is even, otherwise \$-(x^n)\$. This extra check can be done at the start rather than in the middle of a loop. Combining the two you get

if n &lt; 0:
    power = -n
else:
    power = n

if x &lt; 0:
    base = -x
else:
    base = x

result = old_code(base, power)

if base != x and power % 2:
    # (-x)**n == -(x**n) if n is odd, otherwise x**n
    result = -result

if power != n:
    # x**(-n) == 1 / x**n
    result = 1 / result

return result


This probably could bit a little nicer, but hopefully it is very clear what is happening. From this you can write your code assuming both the base and power are positive.



Better algorithm

We can improve the algorithm from O(n) to O(log n), where n is the power, using the idea from russian peasant exponentiation. Alternatively you could implement exponentiation by squaring for the same runtime complexity. We can derive the idea by the following observation

$$x^n = \overbrace{x \times x \times x \times \cdots \times x}^{n}$$

$$x^n = \overbrace{x \times x \times x \times \cdots \times x}^{n/2} \times \overbrace{x \times x \times x \times \cdots \times x}^{n/2}$$

$$x^n = y \times y, y = \overbrace{x \times x \times x \times \cdots \times x}^{n/2}$$

We need to make a slight adjustment if n is odd, as n/2 wont be an integer

$$x^n = x \times \overbrace{x \times x \times x \times \cdots \times x}^{\lfloor n/2 \rfloor} \times \overbrace{x \times x \times x \times \cdots \times x}^{\lfloor n/2 \rfloor}$$

$$x^n = x \times y \times y, y = \overbrace{x \times x \times x \times \cdots \times x}^{\lfloor n/2 \rfloor}$$

We can then work out \$x^{n/2}\$ recursively until some easy to compute base case.

Note: To turn this into a loop we can do the same thing, but starting at lower powers and working up. See the pdf for how to continue.

All in all my suggested code would look something like this

def pow(x, n):
    if n == 0:
        return 1
    if x == 1:
        # New easy check
        return 1
    if x == 0:
        if n &lt; 0:
            # builtin pow throws an exception rather than returning None
            raise ZeroDivisionError("...")
        return 0

    if n &lt; 0:
        power = -n
    else:
        power = n

    if x &lt; 0:
        base = -x
    else:
        base = x

    result = _pow(base, power)

    if base != x and power % 2:
        # (-x)**n == -(x**n) if n is odd, otherwise x**n
        result = -result

    if power != n:
        # x**(-n) == 1 / x**n
        result = 1 / result

    return result

def _pow(base, power):
    """Return base**power
    Assume base &gt; 0, power &gt; 0"""
    if power == 1:
        return base

    y = _pow(base, power // 2)
    result = y * y
    if power % 2:
        result *= base
    return result