2

For an assignment, I must create a program with a function that replaces the "power function" assuming that it is broken for whatever reason. The current model I have works pretty decently, but I'm struggling to get it to work when raising to a 1/2, 1/4, etc. (essentially performing a square root function). I know that the issue lies within floats not cooperating with range, but I personally don't know how to avoid this

def power (value, exp):
    num = 1.0 
    if exp>0:
        for function in range(exp):
            num = num * value 
    elif exp<0:
        for function in range(-exp):
            num = num / value
    else:
        num = 1
    return num

number = float(raw_input("Please enter a the base number you wish to raise to a power (no fractions, decimal allowed): "))
exponent = float(raw_input("Please enter the power you wish to raise the base number to (no fractions, decimal allowed): "))

print "Your base number was:", number
print "You rasied this number to the power of:", exponent
print "The ending product of this operation is:", power(number, exponent)
Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
Christian
  • 37
  • 2

1 Answers1

0

Fractional powers are a bit tricky, but you can use the fact that bn/d = (bn)1/d = d√ bn. See here for details. So you could write a recursive algorithm that

  • reduces the exponent until it is a float between 0 and 1
  • approximates a fraction n/d representing that float, e.g. using fractions or this
  • find the dth root of the n power, e.g. using simple binary search

Code:

def power(b, e):
    # the simple cases
    if e == 0: return 1
    if b in (0, 1): return b
    if e < 0: return 1 / power(b, -e)
    if e >= 1: return b * power(b, e - 1)
    # fractions: b^(n/d) == d-/ b^n
    n, d = float_to_fraction(e)  # see linked answer
    return root(power(b, n), d)

def root(x, r):
    if x < 0: raise ValueError("No roots of negative numbers!")
    low, high = 0, x
    cur = (low + high) / 2
    while high - low > 0.001:
        if power(cur, r) < x:
            low = cur
        else:
            high = cur
        cur = (low + high) / 2
    return cur

Example:

>>> b, e = 1.23, -4.56
>>> b**e
0.38907443175580797
>>> power(b, e))
0.38902984218983117

Or you could just use logarithms, although that might be considered cheating:

>>> math.exp(e * math.log(b))
0.38907443175580797
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • Addendum: Of course, the same could be implemented iteratively instead of using recursion and would probably be faster this way, but that should not really be a concern here and I like the elegance of the recursive definition. Also, there are certainly better ways to compute the nth root, but again, that's not really the point of the question. – tobias_k Feb 10 '18 at 12:48