Newton had a fun way to approximate general roots...
#10
@Pete,

Jack is doing Logs which I know you want to avoid, and your and Newton's scheme still needs to do roots (powers)! the very thing you need a function for so here is old idea I had some time ago.

It does the integer part of root by mult in loop (not very fancy for sure).
Then it converts the fraction to Binary 0's and 1's, it only uses Square Root but over and over again on 2.
I might have it explained better in comments
Code: (Select All)
_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 Function

    '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

Actually this idea might go better here:
https://staging.qb64phoenix.com/showthread.php?tid=881

The approach is similar until we convert the fraction part to Binary.
b = b + ...
Reply


Messages In This Thread
RE: Newton had a fun way to approximate general roots... - by bplus - 09-13-2022, 06:10 PM



Users browsing this thread: 14 Guest(s)