There's a StackExchange puzzle which challeges us to implement power (i.e.
dyad ^) using only the simple arithmetic dyads + - * % and monad | [1]. In
other words, we may not use ^ or ^. or variants.  There are still several
open questions on the puzzle, not least of which involves the domain of
the inputs (can the base be negative?) and range of the outputs (how much
precision is required?), but neverthless we can make some assumptions and
start to sketch an approach.

So, ignoring the "golf" aspect for now, and also (for the moment) any
clever but spirit-evading methods for using ^ without using ^ (including
other primitives which use ^ under the covers), how would you pursue this?
 

I took the naive approach based on the relation  x^y  <=> exp( y * ln(x) )
. Recursing into that, since we don't have ln(y) either, I took another
naive approach based on the relation ln(y) = lb(y) % lb(1x1) where lb is
2&^. . Recursing into that, since we don't have 2&^. either, I had to
resort to an algorithm I found on Wikipedia. Similar comments apply to
estimating exp(y) .  Anyway, I'm getting reasonable results, given that I
don't know what I'm doing:

           10 pow 3     NB. Should be 1000
        999.761

           1p1 ^ 1x1    NB. pi to the e
        22.4592
           1p1 pow 1x1  NB. pretty close
        22.4581

           1x1 ^ 1p1    NB. e to the pi
        23.1407
           1x1 pow 1p1  NB. still pretty close
        23.1396

           1x1 ^ _1p1   NB. negative exponents are ok too
        0.0432139
           1x1 pow _1p1
        0.0432118

           1p1 ^ _1x1
        0.0445253
           1p1 pow _1x1
        0.0445231

So it seems like, precision questions aside, this approach can handle both
integral and rational bases and exponents, and the exponents can have any
sign.  On the other hand, while it handles positive bases ok, negative
bases are iffier (and base 0 just doesn't work):

           _5 ^ 10      NB.  Sometimes they work ok...    
        9.76563e6
           _5 pow 10
        9.75299e6

           _5 ^ _10
        1.024e_7
           _5 pow _10
        1.02267e_7

           _10 ^ 3      NB.  Other times, 
        _1000
           _10 pow 3    NB.  .. not so much
        999.761

This boils down to a difference between the real log, ^. and my substitute:

           ^. _5        NB. ^. can return complex numbers
        1.60944j3.14159
           ln _5        NB. but ln never will
        1.60944

Of course, I could start doing all sorts of fancy tricks (like switching to
a simpler definition when I detect an integral power, or something else
for a negative base) but I was hoping not to; I kind of wanted ^ to fall
out naturally from the mathematical equivalences (again, modulo
precision).  My code is below, for reference, but I'm wondering if I'm
overlooking something, or someone can suggest a potentially more fruitful
tack.

N         =:  64                            NB. Controls precision

pow       =:  exp@:(* ln)~                  NB.  x^y    = exp( y * ln(x) )
 exp      =:  1e5 spow~ 1 + %&1e5           NB.  exp(y) = lim[n -> _] (1 +
y%n)^n
 ln       =:  (lb 1x1) %~ lb                NB.  ln (y) = (lb y) % (lb 1x1)
  lb      =:  (] + lbF@:(% spow~&2)) lbI    NB.  lb (y) = n + lb(y * 2^-n)
where n =: <.2^.y
   spow   =:  */@:#~                        NB.  simple pow (positive
integer exponent)
   lbI    =:  _1 + (0,*/\N#2) I. |          NB.  log-base-2 of an integer
using lookup table
   lbF    =:  BFC +/ .* bits                NB.  (below) Binary Fraction
Coefficients
    BFC   =:  */\. ((N-1)#2) , %65536b10000
    bits  =:  (< (<0) ; 1) { bit^:(<1+N)    NB. See
http://en.wikipedia.org/wiki/Binary_logarithm#Real_number
    bit   =:  itBt@:*~@{.                   NB. Next iteration &
corresponding bit
     itBt =:  ((% {&1 2) , ]) (2&<)

-Dan

[1]  codegolf.SE "Raise to the Power":
     http://codegolf.stackexchange.com/questions/35732/raise-to-the-power

   
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to