Hey guys,

I'm wondering if there is an exponential function? I've been trying to build my own but it doesn't quite work so I don't know what to do.

Carets work fine, if that's what you need? ("x=2 print(x^2)" yields "4")

Are you perhaps making overly large numbers? From the manual:

- PICO-8 numbers only go up to 32767.99. // If you add 1 to a counter each frame, it will overflow after around 18 minutes! |

EDIT:fixed my typo.

I gotcher carrot right here. :D

[8x8] | |

No, truly, a carat is the SHIFT key of 6 "^" so when you use:

PRINT(2^3) |

you will get back the result of 8. Reversing it, (3^2) gives you 9.

Do you see why, because you need to know the difference in this math to use it properly.

Unfortunately, the caret operator doesn't work for non-integer exponents, e.g.: 16^0.5 evaluates to 1, but you want 4.

I had a go at using Newton-Raphson to approximate an exponential function, but didn't have much success, I think due to bumping up against the limits of 16:16 fixed point.

Oww ... That really hurts, Dr. Pete. :( I rely on exponents in high decimals to get the proper 'feel' of experience points and ability games when I write RPGs and RPG Makers.

One such routine I wrote in GFA called RIDE:

FUNCTION Ride(I,N,N2#) IF I < 0 OR N <= 0 THEN RETURN 0 IF I + N + N2# = 0 RETURN 0 ENDIF RETURN INT(((I * N + I ^ N2#) \ N) * N) ENDFUNC |

Lovely, delicious little function I wrote, worked miracles for getting the right curve of growth in numbers.

And you're saying you can't do exponents in decimal values or fractions in PICO ??

Grmmbl ... Are there any kludges yet ?

Here’s a pow() function with decent precision. It relies on sqrt’s precision, and does not use the ^ operator which has terrible precision for large exponents.

function pow(x,a) if (a==0) return 1 if (a<0) x,a=1/x,-a local ret,a0,xn=1,flr(a),x a-=a0 while a0>=1 do if (a0%2>=1) ret*=xn xn,a0=xn*xn,shr(a0,1) end while a>0 do while a<1 do x,a=sqrt(x),a+a end ret,a=ret*x,a-1 end return ret end |

Some examples:

pow(1.8,-3.7) = 0.1134 (should be 0.113629)

pow(17,1.3) = 39.807 (should be 39.77256)

pow(123,1.7) = 3660.404 (should be 3571.40)

pow(1.3,20) = 189.997 (should be 190.05)

pow(1.1,100) = 13764.307 (should be 13780.61)

Trying with some fractions and comparing against standard exponents ...

PRINT(7^1.25) -- 7 incorrect

PRINT(POW(7,1.25) -- 11.465 better

Scientific calculator

7^1.25 -- 11.386035931884500202478626418456 accurate

:D This is impressive work, SamHocevar. I'm adding this routine to my list of useful library routines. If I use it you will most definitely receive credit.

**NICE JOB !!**

@samhocevar can I put your pow() in https://github.com/sparr/pico8lib/ ?

@sparr sure thing! I haven't revisited it in years so it's possible that it can be improved.

Not noted in this thread is that zep updated the ^ operator to do proper fractional and negative powers. It actually returns the same values Sam quotes above for his function, so it may be that zep used the same algorithm.

I also wrote a pow() along the same lines a while back. It runs about the same speed as Sam's and gets a slightly better result for the first example he gives, but it's identical for the rest and for dw's numbers. The difference is probably just luck with roundoffs in the order I do the math.

What's important, though, is that the ^ operator takes about 1/4th of the time that either my or Sam's functions take. It took about 6.33 frames to do 10000 calcs with ^, vs about 25.5 with mine or Sam's. Clearly zep is refunding cycles for the operator. So...

Use the handy operator. Don't use a pow() function. :)

Thanks for the tip. Sometimes it's hard to tell when old stuff on the BBS is still relevant/accurate, and I hadn't taken the time to benchmark this myself yet.

PS: Check out https://github.com/sparr/pico8lib/blob/master/math.p8#L31-L48 if you're interested in accurate fractional exponentiation.

[Please log in to post a comment]