I have a power function pow
that attempts to calculate the value of B
to the power of E
. So far I handle the cases-
1. exponent is 0
2. exponent is non-zero
pow(B,0,1).
pow(B,E,Result):- E2 is E - 1,
pow(B,E2,Result2),
Result is B*Result2.
How can I add another case where the power function can handle negative exponents?
First, one should consider how to define 00. Formally speaking it is indeterminate. It could be zero or it could be 1. As Wolfram's Mathworld says in its article on powers and in its article on zero:
So you should first choose how to define the special case of 00: Is it 0? Is it 1? Is it undefined?
I choose to look at it as being undefined.
That being said, you can look at a positive exponent as indicated repeated multiplication (e.g. 103 is 10*10*10, or 1,000), and you can look at a negative exponent as indicating repeated division (e.g, 10-3 is (((1/10)/10)/10), or 0.001). My inclination, partly because I like the symmetry of this approach and partly to avoid the cuts (since a cut is often a signal that you've not defined the solution properly), would be something like this:
The other approach, as others have noted, is to define a positive exponent as indicating repeated multiplication, and a negative exponent as indicating the reciprocal of the positive exponent, so 103 is 10*10*10 or 1,000, and 10-3 is 1/(103), or 1/1,000 or 0.001. To use this definition, I'd again avoid the cuts and do something like this:
To start, your second clause is non tail recursive (you can read about the subject here). It means that eventually, you will run out of call stack memory when running it. A good thing would be to use an accumulator to make it tail recursive. You can achieve that as follows :
Then, you can simply handle the negative case by adding this clause on top of the others (it simply tells prolog that a negative power is the inverse of the positive one) :
Note that you can do it directly with your code :
Plus, we now introduced a very red cut (see here for the meaning of red cut if necessary). So it'd be better to turn into a green cut with this modification :
Don't forget that
a^(2b) = (a^b)^2
andx^2 = x*x
. It is ok to call a tail-recursive working predicate with accumulator, in a non-tail fashion, from a top-level "UI" predicate. That way you don't have to implement working predicate for negative powers but rather reuse the one for positive power, and alter its result in the top-level predicate (I see this has already been suggested):