Wow in QB64, this power estimator is on par with the ^ operator!

`_TITLE "Power Function 2 by bplus"`

'QB64 X 64 version 1.2 20180228/86 from git b301f92

' started 2018-07-23 Naalaa has no power function (or operator), so I wrote a power function for it.

' ''Power pack the short version.txt

' ''written for Naalaa 6 by bplus posted 2018-07-23

' ''extracted from large test of fractions, random number functions, string... in Power test.txt

' 2018-07-24 Power Function 2 split is replaced with two much smaller and very handy string functions.

' OMG the crazy thing worked! It produced decent estimates of roots given the limitations of precision...

' Now I want to see how well it works with far greater precision available. So here we are, looking to see

' how this function compares to the regualar ^ operator in QB64.

'from Naalaa comments:

' The main purpose of this code: to demo a power function for real numbers,

' I had an idea for how real numbers to the power of real numbers might be done ie x ^ y = ?

' This means that not only can you take SQR of a number, you can get cube or cube root, quartic, 5th 6th... roots and any multiple

' It came from this simple idea

' 2 ^ 3.5 = 2 ^ 3 * 2 ^ .5 = 8 * Sqr(2)

' 3 ^ 3.5 = 3 ^ 3 * 3 ^ .5 = 27 * Sqr(3)

' so 2 ^ 3.25 = 2 ^ 3 * 2 ^ .25

' what is 2 ^ .25 ? It is sqr(sqr(2)) !

' likewise 2 ^ 3.125 = 2 ^ 3 * 2 ^ 1/8

' what is 2 ^ 1/8 ? It is sqr(sqr(sqr(2))) !

' any decimal can be written as a sum of fraction powers of 2 ie 1/2^n, as any integer can be written in powers of 2.

' in binary expansions

' 1/2 = .1 or .5 base 10

' 1/4 = .01 or .25 base 10

' 1/8 = .001 or .125 base 10

' 1/16 = .0001 or .0625 base 10

' So with binary expansion of decimal, we can SQR and multiply our way to an estimate

' of any real number to the power of another real number using binary expansion of

' the decimal parts as long as we stay in Naalaa integer limits and are mindful of precision.

CONST wW = 800

CONST wH = 600

SCREEN _NEWIMAGE(wW, wH, 32)

_SCREENMOVE 360, 60

_DEFINE A-Z AS _FLOAT

DO

PRINT "Testing the power(x, pow) function:"

INPUT "(nothing) quits, Please enter a real number to raise to some power. x = "; x

IF x = 0 THEN EXIT DO

INPUT "(nothing) quits, Please enter a real number for the power. pow = ", pw

IF pw = 0 THEN EXIT DO

result = power(x, pw)

PRINT result; " is what we estimate for"; x; " raised to power of"; pw

PRINT x ^ pw; " is what the ^ operator gives us."

PRINT

LOOP

PRINT

PRINT "This is matching the ^ operator very well! This code is clear proof of concept!"

PRINT " OMG, it worked!!!"

SLEEP

' A power function for real numbers (small ones but still!)

' x to the power of pow

FUNCTION power## (x AS _FLOAT, pow AS _FLOAT)

'this sub needs: bExpand60$, leftOf$, rightOf$

DIM build AS _FLOAT

r$ = "0" + STR$(pow) 'in case pow starts with decimal

integer$ = leftOf$(r$, ".")

build = 1.0

IF integer$ <> "0" THEN

p = VAL(integer$)

FOR i = 1 TO p

build = build * x

NEXT

END IF

'that takes care of integer part

n$ = rightOf$(r$, ".")

IF n$ = "" THEN power = build: EXIT SUB

'remove 0's to right of main digits

ld = LEN(n$)

WHILE RIGHT$(n$, 1) = "0"

n$ = LEFT$(n$, ld - 1)

ld = LEN(n$)

WEND

'note: we are pretending that the ^ operator is not available, so this is hand made integer power

denom& = 10

FOR i = 2 TO ld

denom& = denom& * 10

NEXT

'OK for bExpand60$ don't have to simplify fraction and that saves us having to extract n and d again from n/d

bs$ = bExpand60$(VAL(n$), denom&)

'at moment we haven't taken any sqr of x

runningXSQR = x

'run through all the 0's and 1's in the bianry expansion, bs$, the fraction part of the power float

FOR i = 1 TO LEN(bs$)

'this is the matching sqr of the sqr of the sqr... of x

runningXSQR = SQR(runningXSQR)

'for every 1 in the expansion, multiple our build with the running sqr of ... sqr of x

IF MID$(bs$, i, 1) = "1" THEN build = build * runningXSQR

NEXT

'our build should now be an estimate or x to power of pow

power = build

END FUNCTION

'write a series of 1s and 0s that represent the decimal fraction n/d in binary 60 places long

FUNCTION bExpand60$ (nOver&, d&)

DIM b AS _FLOAT, r AS _FLOAT

' b for base

b = 0.5

' r for remainder

r = nOver& / d&

' s for string$ 0's and 1's that we will build and return for function value

s$ = ""

' f for flag to stop

f% = 0

' c for count to track how far we are, don't want to go past 20

c% = 0

WHILE f% = 0

IF r < b THEN

s$ = s$ + "0"

ELSE

s$ = s$ + "1"

IF r > b THEN

r = r - b

ELSE

f% = 1

END IF

END IF

c% = c% + 1

IF c% >= 60 THEN f% = 1

b = b * 0.5

WEND

bExpand60$ = s$

END FUNCTION

FUNCTION leftOf$ (source$, of$)

posOf = INSTR(source$, of$)

IF posOf > 0 THEN leftOf$ = MID$(source$, 1, posOf - 1)

END FUNCTION

FUNCTION rightOf$ (source$, of$)

posOf = INSTR(source$, of$)

IF posOf > 0 THEN rightOf$ = MID$(source$, posOf + LEN(of$))

END FUNCTION