range error - or "How to take the factorial of a huge number"
Jim Witte
jswitte at bloomington.in.us
Fri Apr 9 01:05:32 EDT 2004
.Oh God,
Just thinking off the top of my head, I'm thinking recusion overflow
(unless the RunRev compiler automatically CPS's recursive function
automatically, which I doubt) Try this script (written off the top of
my head
function factorial (n)
return factAPS(n, 1) -- start the accumulator at 1
end factorial
function factAPS (n, a)
if (n=1) then
return a -- we stop multiplying the accumlator at n=1 because a*1=a
else
put a*n into a -- update the accumulator
factAPS(n-1, a)
end if
end factAPS
This is factorial in acculator-passing-style, which is closely
related to continuation-passing-style, but I can't do the CPS in my
head, and I think it would just build up a great long list of numbers
instead (the list-representation of the continuation). If MetaCard is
coded right, the factAPS call at the end should be turned into a jump
(since nothing, like a *, is "waiting" for it's result). This will
avoid a recursion stack, and most likely speed up the code a GREAT deal
(though that depends on the specifics of how MetaCard's bytecode
interpreter works).
If MetaCard supports a goto statement, the above could (possibly) be
further optimized to this:
function factorial (n)
put n into gn
put 1 into ga
label factAPS:
if (gn=1) then -- line 1
return ga
else
put ga*gn into ga
put gn-1 into gn -- line 2
goto factAPS
end factorial
This is functionally *exactly* the same code as above, except that I
explicitly registerized it (with the variables gn and ga), and made the
goto explicit. But it is still guaranteed to terminate because gn is
always decreasing (line 2), and the return statement is invoked when gn
gets down to 1 (line 1). This might be just a hair quicker that the
first function, depending on how MetaCard optimizes things (if it does,
it will do this transformation automatically - indeed, just as I did.
If it were really good, it would take the OP's factorial function, and
then turn it into the two code samples above - automatically.)
Another possibility (a little less accurate though) for calculating
really big factorials is to use Sterling's formula and the gamma
function. Look at
http://mathworld.wolfram.com/StirlingsApproximation.html
for a technical (read, integral calculus, although all that is is a
nifty name for an infinite sum) description.
The function would be:
on factorialApprox (n)
return sqrt( 2*pi) * (n^ (N+1/2)) * exp( -n );
end factorialApprox
in conventional math notation, that's
n! ~
-------------- next part --------------
or sqrt(2 pi) n^(n+1/2) e^(-n)
if the gif didn't come through
(Parts copyright MathWorld, ? 1999 CRC Press LLC, ? 1999-2004 Wolfram
Research, Inc.)
Jim
> When I attempt to calculate the factorial of numbers > 169 using the
> following function:
>
> function factorial theNumber
> if theNumber <= 1 then return 1
> else return theNumber * factorial(theNumber -1)
> end factorial
>
> I get the following error. Anybody seen this before?
>
> executing at 11:46:47 PM
>
> Type Operators *: range error (overflow)
> Object Bed Adequacy
> Line else return theNumber * factorial(theNumber -1)
> Hint factorial
>
> Is there a work around for this?
>
> OSX 10.2.8, Rev 2.1.2, 512 MB of RAM
>
> Thanks
>
> Steve
>
> Stephen R. Messimer, PA
> 208 1st Ave. South
> Escanaba, MI 49829
> http://www.messimercomputing.com
> --
> Build Computer-Based Training modules FAST with preceptorTools? --
> version 1.0.5 available Now!
>
> _______________________________________________
> use-revolution mailing list
> use-revolution at lists.runrev.com
> http://lists.runrev.com/mailman/listinfo/use-revolution
>
More information about the use-livecode
mailing list