Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
KISS MY ASCII GOOD PI!
#21
(08-25-2022, 08:12 PM)mnrvovrfc Wrote: Why not just "printf" instead of "__mingw_printf"? Because you're including "stdio.h" then "printf()" should be available. I tried to compile your program as it was, "gcc" asked me if I meant "builtin_printf()" or alike. After I forgot what option for linker so it links to math library...

"__mingw-printf" is for representing large numbers like long double.

So, "__mingw_printf("%.12Lf"...) is for displayin great numbers.

[Image: chud-in-C-2022-08-26-010015.jpg]
Reply
#22
Pete
my only intention in posting the string version of Ramanujan was for you to incorporate it into your string-math routines
Reply
#23
(08-26-2022, 12:50 AM)Jack Wrote: Pete
my only intention in posting the string version of Ramanujan was for you to incorporate it into your string-math routines

I did that, too.

Code: (Select All)
WIDTH 180, 42
_SCREENMOVE 0, 0
DIM SHARED limit&&, betatest%
digits% = 10
limit&& = digits% + 7
betatest% = 0
DIM AS STRING n, m, c, sum, f, f4, f4k, c1, c2, c3, c34k, t1, t2, t3
DIM AS LONG k, k4
DIM t AS DOUBLE

FOR pete% = 0 TO 16
    digits% = pete% + 10 + pete% * 8
    limit&& = digits% + 7
    t = TIMER
    c1 = "1103"
    c2 = "26390"
    c3 = "396"
    f = "1"
    f4k = "1"
    sum = "1103"
    c34k = "1"
    k4 = 0
    t1 = c3
    t2 = c3
    sm t1, "*", t2, c3
    t1 = c3
    t2 = c3
    sm t1, "*", t2, c3

    FOR k = 1 TO digits% / (7.984)
        t1 = f
        sm STR$(k), "*", t1, f
        IF betatest% THEN PRINT "results = "; f: SLEEP
        t1 = f: t2 = f
        sm t1, "*", t2, f4
        IF betatest% THEN PRINT "results = "; f4: SLEEP
        t1 = f4: t2 = f4
        sm t1, "*", t2, f4
        IF betatest% THEN PRINT "results = "; f4: SLEEP
        t1 = c34k
        sm c3, "*", t1, c34k
        IF betatest% THEN PRINT "results = "; c34k: SLEEP
        t1 = STR$(k4 + 1)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 2)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 3)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 4)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        k4 = k4 + 4
        t1 = STR$(k)
        sm t1, "*", c2, t2
        IF betatest% THEN PRINT "results = "; t2: SLEEP
        sm c1, "+", t2, t1
        IF betatest% THEN PRINT "results = "; t1: SLEEP
        sm f4k, "*", t1, t2
        IF betatest% THEN PRINT "results = "; t2: SLEEP
        sm f4, "*", c34k, t1
        IF betatest% THEN PRINT "results = "; t1: SLEEP
        sm t2, "/", t1, t3
        IF betatest% THEN PRINT "results = "; t3: SLEEP
        t1 = sum
        sm t1, "+", t3, sum
        IF betatest% THEN PRINT "sum =   "; sum: SLEEP
        CALL pi(t1, sum, k)
    NEXT
    COLOR 14, 0: PRINT "Ramanujan pi = "; MID$("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481", 1, 11 + (k - 2) * 8)
    COLOR 7, 0
    t = TIMER - t
    PRINT "Time:"; t: PRINT
NEXT pete%
END

SUB pi (t1$, sum$, k)
    square_root "8", t1$
    IF betatest% THEN PRINT "Pi # = "; t1$: SLEEP
    t2$ = "9801"
    sm t1$, "/", t2$, t3$
    IF betatest% THEN PRINT "Pi # = "; t3$: SLEEP
    sm t3$, "*", sum$, t2$
    IF betatest% THEN PRINT "Pi # = "; t2$: SLEEP
    sm t1$, "/", t2$, t3$
    IF betatest% THEN PRINT "Pi # = "; t3$: SLEEP
    sm "1", "/", t2$, t1$
    IF betatest% THEN PRINT "Pi # = "; t1$: SLEEP
    PRINT "loop #"; LTRIM$(STR$(k));: LOCATE , 10: PRINT " pi = "; MID$(t1$, 1, 11 + (k - 1) * 8)
END SUB

SUB sm (s_var1$, operator$, s_var2$, runningtotal$)
    DIM AS _INTEGER64 a, c, aa, cc, s, ss
    stringmatha$ = s_var1$: stringmathb$ = s_var2$

    SELECT CASE operator$
        CASE "+", "-"
            GOSUB string_add_subtract_new
        CASE "*"
            GOSUB string_multiply_new
        CASE "/"
            GOSUB string_divide
        CASE ELSE
            PRINT "Error, no operator selected. operator$ = "; operator$: END
    END SELECT
    EXIT SUB

    string_divide:
    terminating_decimal% = 0: divsign% = 0: divremainder& = 0: divremainder$ = "": divplace& = 0: divplace2& = 0: quotient$ = "": divcarry& = 0
    divbuffer& = LEN(stringmathb$) - LEN(stringmatha$)
    IF divbuffer& < 0 THEN divbuffer& = 0
    d2dividend$ = stringmatha$
    d1divisor$ = stringmathb$
    IF LEFT$(d1divisor$, 1) = "0" AND LEN(d1divisor$) = 1 THEN PRINT "Division by zero not allowed.": divsign% = 0: EXIT SUB
    IF LEFT$(d1divisor$, 1) = "-" THEN divsign% = -1: d1divisor$ = MID$(d1divisor$, 2)
    IF LEFT$(d2dividend$, 1) = "-" THEN
        IF divsign% THEN
            divsign% = 0
        ELSE
            divsign% = -1
        END IF
        d2dividend$ = MID$(d2dividend$, 2)
    END IF
    IF INSTR(d1divisor$, ".") <> 0 THEN
        DO UNTIL RIGHT$(d1divisor$, 1) <> "0"
            d1divisor$ = MID$(d1divisor$, 1, LEN(d1divisor$) - 1) ' Strip off trailing zeros
        LOOP
        divplace& = LEN(d1divisor$) - INSTR(d1divisor$, ".")
        d1divisor$ = MID$(d1divisor$, 1, INSTR(d1divisor$, ".") - 1) + MID$(d1divisor$, INSTR(d1divisor$, ".") + 1) ' Strip off decimal point.
        DO UNTIL LEFT$(d1divisor$, 1) <> "0"
            d1divisor$ = MID$(d1divisor$, 2) ' Strip off leading zeros for divisors smaller than .1
        LOOP
    END IF

    IF INSTR(d2dividend$, ".") <> 0 THEN
        d2dividend$ = d2dividend$ + STRING$(divplace& - LEN(d2dividend$) - INSTR(d2dividend$, "."), "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace2& = INSTR(d2dividend$, ".")
        DO UNTIL RIGHT$(d2dividend$, 1) <> "0"
            d2dividend$ = MID$(d2dividend$, 1, LEN(d2dividend$) - 1) ' Strip off trailing zeros
        LOOP
        d2dividend$ = MID$(d2dividend$, 1, INSTR(d2dividend$, ".") - 1) + MID$(d2dividend$, INSTR(d2dividend$, ".") + 1) ' Strip off decimal point.
    ELSE
        d2dividend$ = d2dividend$ + STRING$(divplace&, "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace& = 0
    END IF
    DO
        DO
            divremainder& = divremainder& + 1: divremainder$ = divremainder$ + MID$(d2dividend$, divremainder&, 1)
            IF MID$(d2dividend$, divremainder&, 1) = "" THEN
                IF divremainder$ = STRING$(LEN(divremainder$), "0") AND LEN(quotient$) > LEN(d2dividend$) THEN
                    divflag% = -1
                    terminating_decimal% = -1
                    EXIT DO
                END IF
                divcarry& = divcarry& + 1
                IF divcarry& = 1 THEN divplace3& = divremainder& - 1
                IF divcarry& > limit&& + 1 + divbuffer& THEN
                    divflag% = -2: EXIT DO
                END IF
                divremainder$ = divremainder$ + "0" ' No more digits to bring down.
            END IF
            IF LEN(divremainder$) > LEN(d1divisor$) OR LEN(divremainder$) = LEN(d1divisor$) AND divremainder$ >= d1divisor$ THEN EXIT DO
            quotient$ = quotient$ + "0"
        LOOP
        IF divflag% THEN divflag% = 0: EXIT DO

        FOR div_i% = 9 TO 1 STEP -1
            stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
            GOSUB string_multiply_new ' Gets runningtotal$
            tempcutd$ = divremainder$ ' divremainder$ can be 00 or other leading zero values.
            DO
                IF LEN(tempcutd$) = 1 THEN EXIT DO
                IF LEFT$(tempcutd$, 1) = "0" THEN
                    tempcutd$ = MID$(tempcutd$, 2)
                ELSE
                    EXIT DO
                END IF
            LOOP
            IF LEN(tempcutd$) > LEN(runningtotal$) OR LEN(tempcutd$) = LEN(runningtotal$) AND runningtotal$ <= tempcutd$ THEN EXIT FOR
        NEXT
        quotient$ = quotient$ + LTRIM$(STR$(div_i%))
        stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
        GOSUB string_multiply_new ' Gets runningtotal$
        stringmatha$ = divremainder$: stringmathb$ = runningtotal$
        operator$ = "-": GOSUB string_add_subtract_new
        divremainder$ = runningtotal$
    LOOP

    IF divplace& = 0 AND divplace2& = 0 THEN divplace& = divplace3&
    IF divplace2& THEN divplace& = divplace& + divplace2& - 1
    IF quotient$ = "" THEN divplace& = 0 ' dividend is zero.
    IF divplace& OR divplace2& THEN
        quotient$ = MID$(quotient$, 1, divplace&) + "." + MID$(quotient$, divplace& + 1)
        DO UNTIL RIGHT$(quotient$, 1) <> "0"
            quotient$ = MID$(quotient$, 1, LEN(quotient$) - 1) ' Strip off trailing zeros
        LOOP
        IF RIGHT$(quotient$, 1) = "." THEN quotient$ = MID$(quotient$, 1, LEN(quotient$) - 1) ' Strip off abandoned decimal.
    END IF
    DO UNTIL LEFT$(quotient$, 1) <> "0"
        quotient$ = MID$(quotient$, 2) ' Strip off leading zeros
    LOOP
    IF quotient$ = "" THEN quotient$ = "0": divsign% = 0
    stringmathb$ = quotient$: quotient$ = ""

    IF stringmathb$ = "overflow" THEN divsign% = 0: EXIT SUB

    runningtotal$ = stringmathb$: stringmathb$ = ""
    IF divsign% THEN runningtotal$ = "-" + runningtotal$

    IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
    RETURN

    string_add_subtract_new:
    a1$ = stringmatha$: b1$ = stringmathb$
    s = 18: i&& = 0: c = 0

    a$ = stringmatha$: b$ = stringmathb$: op$ = operator$

    IF op$ = "-" THEN
        IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2) ELSE b$ = "-" + b$
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
        ' Line up decimal places by inserting trailing zeros.
        IF dec_b&& > dec_a&& THEN
            j&& = dec_b&&
            a$ = a$ + STRING$(dec_b&& - dec_a&&, "0")
        ELSE
            j&& = dec_a&&
            b$ = b$ + STRING$(dec_a&& - dec_b&&, "0")
        END IF
    END IF

    IF LEFT$(a$, 1) = "-" OR LEFT$(b$, 1) = "-" THEN
        IF LEFT$(a$, 1) = "-" AND LEFT$(b$, 1) = "-" THEN
            sign$ = "--": a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF LEFT$(a$, 1) = "-" THEN a$ = MID$(a$, 2): sign_a$ = "-"
            IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2): sign_b$ = "-"

            IF LEFT$(a1$, 1) = "-" THEN a1_x$ = MID$(a1$, 2) ELSE a1_x$ = a1$
            IF LEFT$(b1$, 1) = "-" THEN b1_x$ = MID$(b1$, 2) ELSE b1_x$ = b1$

            string_compare a1_x$, b1_x$, gl%

            IF gl% < 0 THEN
                IF LEN(sign_b$) THEN sign$ = "-": SWAP a$, b$
            ELSE
                IF LEN(sign_a$) THEN sign$ = "-": SWAP sign_a$, sign_b$
            END IF
        END IF
    END IF

    z$ = ""

    DO
        i&& = i&& + s
        x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
        x2$ = MID$(b$, LEN(b$) - i&& + 1, s)
        zeros% = LEN(x1$): IF LEN(x2$) > zeros% THEN zeros% = LEN(x2$)
        a = VAL(sign_a$ + x1$) + VAL(sign_b$ + x2$) + c
        IF x1$ + x2$ = "" AND c = 0 THEN EXIT DO
        c = 0
        IF a > VAL(STRING$(s, "9")) THEN a = a - 10 ^ s: c = 1
        IF a < 0 THEN a = a + 10 ^ s: c = -1
        tmp$ = LTRIM$(STR$(a))
        z$ = STRING$(zeros% - LEN(tmp$), "0") + tmp$ + z$
    LOOP

    IF decimal% THEN
        z$ = MID$(z$, 1, LEN(z$) - j&&) + "." + MID$(z$, LEN(z$) - j&& + 1)
    END IF

    ' Remove any leading zeros.
    DO
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ELSE EXIT DO
    LOOP

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = LEFT$(sign$, 1) + z$

    runningtotal$ = z$

    sign$ = "": sign_a$ = "": sign_b$ = "": i&& = 0: j&& = 0: decimal% = 0: c = 0
    RETURN

    string_multiply_new:
    z$ = "": sign$ = "": mult&& = 0: h&& = 0: i&& = 0: j&& = 0: c = 0: decimal% = 0
    zz$ = "": ii&& = 0: jj&& = 0
    s = 8: ss = 18

    a$ = stringmatha$: b$ = stringmathb$

    IF INSTR(a$, "-") <> 0 OR INSTR(b$, "-") <> 0 THEN
        IF INSTR(a$, "-") <> 0 AND INSTR(b$, "-") <> 0 THEN
            a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF INSTR(a$, "-") <> 0 THEN a$ = MID$(a$, 2) ELSE b$ = MID$(b$, 2)
            sign$ = "-"
        END IF
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
    END IF

    IF LEN(a$) < LEN(b$) THEN SWAP a$, b$ ' Needed so x1$ is always the largest for leading zero replacements.

    DO
        h&& = h&& + s: i&& = 0
        x2$ = MID$(b$, LEN(b$) - h&& + 1, s)
        WHILE -1
            i&& = i&& + s
            x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
            a = VAL(sign_a$ + x1$) * VAL(sign_b$ + x2$) + c
            c = 0
            tmp$ = LTRIM$(STR$(a))
            IF LEN(tmp$) > s THEN c = VAL(MID$(tmp$, 1, LEN(tmp$) - s)): tmp$ = MID$(tmp$, LEN(tmp$) - s + 1)
            z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
            IF i&& >= LEN(a$) AND c = 0 THEN EXIT WHILE
        WEND

        jj&& = jj&& + 1

        IF jj&& > 1 THEN
            ii&& = 0: cc = 0
            aa$ = holdaa$
            bb$ = z$ + STRING$((jj&& - 1) * s, "0")

            DO
                ii&& = ii&& + ss
                xx1$ = MID$(aa$, LEN(aa$) - ii&& + 1, ss)
                xx2$ = MID$(bb$, LEN(bb$) - ii&& + 1, ss)
                zeros% = LEN(xx1$): IF LEN(xx2$) > zeros% THEN zeros% = LEN(xx2$)
                aa = VAL(xx1$) + VAL(xx2$) + cc
                IF xx1$ + xx2$ = "" AND cc = 0 THEN EXIT DO ' Prevents leading zeros.
                cc = 0
                IF aa > VAL(STRING$(ss, "9")) THEN aa = aa - 10 ^ ss: cc = 1
                tmp$ = LTRIM$(STR$(aa))
                '''zz$ = STRING$(LEN(xx1$) - LEN(tmp$), "0") + tmp$ + zz$
                zz$ = STRING$(zeros% - LEN(tmp$), "0") + tmp$ + zz$
            LOOP

            DO WHILE LEFT$(zz$, 1) = "0"
                IF LEFT$(zz$, 1) = "0" THEN zz$ = MID$(zz$, 2)
            LOOP
            IF zz$ = "" THEN zz$ = "0"

            holdaa$ = zz$
        ELSE
            holdaa$ = z$ + STRING$(jj&& - 1, "0")
        END IF

        z$ = "": zz$ = ""

    LOOP UNTIL h&& >= LEN(b$)

    z$ = holdaa$

    IF decimal% THEN
        DO UNTIL LEN(z$) >= dec_a&& + dec_b&&
            z$ = "0" + z$
        LOOP

        z$ = MID$(z$, 0, LEN(z$) - (dec_a&& + dec_b&& - 1)) + "." + MID$(z$, LEN(z$) - (dec_a&& + dec_b&&) + 1)

        DO UNTIL RIGHT$(z$, 1) <> "0" AND RIGHT$(z$, 1) <> "."
            z$ = MID$(z$, 1, LEN(z$) - 1)
        LOOP
    END IF

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = sign$ + z$

    decimal% = 0: sign$ = ""

    runningtotal$ = z$
    RETURN
END SUB

SUB string_compare (compa$, compb$, gl%)
    DO
        ' Remove trailing zeros after a decimal point.
        IF INSTR(compa$, ".") THEN
            DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                compa$ = MID$(compa$, 1, LEN(compa$) - 1)
            LOOP
        END IF
        IF INSTR(compb$, ".") THEN
            DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                compb$ = MID$(compb$, 1, LEN(compb$) - 1)
            LOOP
        END IF

        IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
        IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

        ' A - and +
        IF LEFT$(compa$, 1) = "-" THEN j% = -1
        IF LEFT$(compb$, 1) = "-" THEN k% = -1
        IF k% = 0 AND j% THEN gl% = -1: EXIT DO
        IF j% = 0 AND k% THEN gl% = 1: EXIT DO

        ' A decimal and non-decimal.
        j% = INSTR(compa$, ".")
        k% = INSTR(compb$, ".")

        IF j% = 0 AND k% THEN
            IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
            EXIT DO
        END IF
        IF k% = 0 AND j% THEN
            IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
            EXIT DO
        END IF

        ' Both decimals.
        IF j% THEN
            IF compa$ > compb$ THEN
                gl% = 1
            ELSEIF compa$ = compb$ THEN gl% = 0
            ELSEIF compa$ < compb$ THEN gl% = -1
            END IF
            EXIT DO
        END IF

        ' Both positive or both negative whole numbers.
        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

SUB square_root (x$, sqrt$)
    oldy$ = "": sqrt$ = ""

    IF INSTR(x$, ".") THEN
        decx$ = MID$(x$, 1, INSTR(x$, ".") - 1)
        x$ = MID$(x$, 1, INSTR(x$, ".") - 1) + MID$(x$, INSTR(x$, ".") + 1)
        IF LEN(x$) = 1 THEN x$ = x$ + "0"
    ELSE
        decx$ = x$
    END IF

    j&& = LEN(decx$)

    ' VAL() okay, one character eval.
    IF VAL(RIGHT$(LTRIM$(STR$(j&&)), 1)) / 2 = VAL(RIGHT$(LTRIM$(STR$(j&&)), 1)) \ 2 THEN
        i&& = 1 ' Even number length.
    ELSE
        i&& = 0 ' Odd number length.
    END IF

    DO
        sm z$, "-", k$, runningtotal$
        z$ = runningtotal$ + (MID$(x$, i&&, 2))
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ' Remove leading zeros

        oldy$ = ""
        FOR j&& = 1 TO 10
            IF i&& > 1 THEN
                sm sqrt$, "*", "2", y$
                y$ = y$ + LTRIM$(STR$(j&&))
            ELSE
                y$ = LTRIM$(STR$(j&&))
            END IF

            sm y$, "*", LTRIM$(STR$(j&&)), runningtotal$

            string_compare runningtotal$, z$, gl%
            IF gl% > -1 THEN
                IF gl% = 0 THEN
                    h% = 0: oldy$ = y$ ' Perfect square division.
                ELSE
                    h% = 1
                END IF
                sm oldy$, "*", LTRIM$(STR$(j&& - h%)), runningtotal$

                IF STRING$(LEN(z$), "0") = z$ AND runningtotal$ = "0" AND i&& >= LEN(decx$) THEN EXIT DO

                IF dpx&& = 0 THEN ' Limited to && size unless converted to string.
                    IF i&& >= LEN(decx$) THEN
                        dpx&& = INT(LEN(decx$) / 2 + .5)
                        IF dpx&& = 0 THEN dpx&& = -1
                    END IF
                END IF

                IF betatest% < -1 THEN PRINT "Sqrt "; sqrt$; " * 2 = ";: COLOR 2, 0: PRINT LTRIM$(STR$(VAL(sqrt$) * 2));: COLOR 7, 0: PRINT LTRIM$(STR$(j&& - h%)); " * "; LTRIM$(STR$(j&& - h%)); " ="; VAL(oldy$) * (j&& - h%)
                sqrt$ = sqrt$ + LTRIM$(STR$(j&& - h%))

                sm oldy$, "*", LTRIM$(STR$(j&& - h%)), runningtotal$
                k$ = runningtotal$

                IF betatest% < -1 THEN PRINT "Remainder "; z$; " minus "; k$; " = ";
                EXIT FOR
            END IF
            oldy$ = y$
        NEXT

        i&& = i&& + 2
        IF LEN(z$) >= limit&& THEN EXIT DO
        x$ = x$ + "00"
    LOOP

    IF dpx&& THEN
        sqrt$ = MID$(sqrt$, 0, dpx&& + 1) + "." + MID$(sqrt$, dpx&& + 1)
    END IF
END SUB


It isn't quite as fast. What I've noticed is my routines tend to take the decimal places out further than necessary for some calculations. My limit&& variable needs to be slightly more than the number of digits to obtain the desired results. Changing that variable has some impact on the final decimal places. My hunch is other methods of calculation use rounding for the final digits, and significant figures in the calculations. Mine does not use either.

I would also need to speed up the square root and division modules a bit. The chunk multiplication, addition, and subtraction are quite fast. That was a nice improvement. Over-all the work is progressing nicely, but I may be leaving my comfort zone when it comes to the mathematical mechanics.

Thanks for all your help on this. It is great for beta-testing my new string routines!

Pete

Edit: Found one bug and fixed the issue in the code.
Reply
#24
Interesting to note that with both string math routines, Treebeard's and mine, pi to 28 digits and 36 digits is incorrect by over 1 on the last digit, and I don't see it as a rounding situation. All other iterations of 10 to 150 appear to be correct, except these. So to correct this, both routines would have to lengthen the value of the square root of 8. I did that by an extra 20-digits, and it fixed the aforementioned discrepancies. Nice; however I wonder what the accepted value of the square root of 8 is for mathematicians who have worked with this formula?

Pete
Reply
#25
Okay, what I see is a need to have the square root of 8 always returned with more digit, and possibly at least the same number of digits, than the output of pi. To that end, I set that number to 200 digits for the square root calculation and noted all digits of pi 10, 18, 26, 34, 50... up to 150 are now all correct. This same adjustment would have to be applied using the Treebeard string math routines.

Updated code. The grey digits are not part of the comparison. I included them to check what the last significant pi digit should be.

Code: (Select All)
WIDTH 180, 42
_SCREENMOVE 0, 0
DIM SHARED sqrt$, limit&&, betatest%
betatest% = 0
DIM AS STRING n, m, c, sum, f, f4, f4k, c1, c2, c3, c34k, t1, t2, t3
DIM AS LONG k, k4
DIM t AS DOUBLE

limit&& = 200: square_root "8", sqrt$ ' Limit must be as many or more digits than the max digits of the returned value for pi.

FOR pete% = 0 TO 16
    digits% = pete% + 10 + pete% * 8
    limit&& = digits% + 7
    t = TIMER
    c1 = "1103"
    c2 = "26390"
    c3 = "396"
    f = "1"
    f4k = "1"
    sum = "1103"
    c34k = "1"
    k4 = 0
    t1 = c3
    t2 = c3
    sm t1, "*", t2, c3
    t1 = c3
    t2 = c3
    sm t1, "*", t2, c3

    FOR k = 1 TO digits% / (7.984)
        t1 = f
        sm STR$(k), "*", t1, f
        IF betatest% THEN PRINT "results = "; f: SLEEP
        t1 = f: t2 = f
        sm t1, "*", t2, f4
        IF betatest% THEN PRINT "results = "; f4: SLEEP
        t1 = f4: t2 = f4
        sm t1, "*", t2, f4
        IF betatest% THEN PRINT "results = "; f4: SLEEP
        t1 = c34k
        sm c3, "*", t1, c34k
        IF betatest% THEN PRINT "results = "; c34k: SLEEP
        t1 = STR$(k4 + 1)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 2)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 3)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 4)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        k4 = k4 + 4
        t1 = STR$(k)
        sm t1, "*", c2, t2
        IF betatest% THEN PRINT "results = "; t2: SLEEP
        sm c1, "+", t2, t1
        IF betatest% THEN PRINT "results = "; t1: SLEEP
        sm f4k, "*", t1, t2
        IF betatest% THEN PRINT "results = "; t2: SLEEP
        sm f4, "*", c34k, t1
        IF betatest% THEN PRINT "results = "; t1: SLEEP
        sm t2, "/", t1, t3
        IF betatest% THEN PRINT "results = "; t3: SLEEP
        t1 = sum
        sm t1, "+", t3, sum
        IF betatest% THEN PRINT "sum =   "; sum: SLEEP
        CALL pi(t1, sum, k)
    NEXT
    COLOR 14, 0: PRINT "Ramanujan pi = "; MID$("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481", 1, 11 + (k - 2) * 8)
    COLOR 7, 0
    t = TIMER - t
    PRINT "Time:"; t: PRINT
NEXT pete%
END

SUB pi (t1$, sum$, k)
    REM square_root "8", sqrt$
    IF betatest% THEN PRINT "Pi # = "; sqrt$: SLEEP
    t2$ = "9801"
    sm sqrt$, "/", t2$, t3$
    IF betatest% THEN PRINT "Pi # = "; t3$: SLEEP
    sm t3$, "*", sum$, t2$
    IF betatest% THEN PRINT "Pi # = "; t2$: SLEEP
    sm t1$, "/", t2$, t3$
    IF betatest% THEN PRINT "Pi # = "; t3$: SLEEP
    sm "1", "/", t2$, t1$
    IF betatest% THEN PRINT "Pi # = "; t1$: SLEEP
    PRINT "loop #"; LTRIM$(STR$(k));: LOCATE , 10: PRINT " pi = "; MID$(t1$, 1, 11 + (k - 1) * 8);: COLOR 8, 0: PRINT MID$(t1$, 11 + (k - 1) * 8 + 1, 4): COLOR 7, 0
END SUB

SUB sm (s_var1$, operator$, s_var2$, runningtotal$)
    DIM AS _INTEGER64 a, c, aa, cc, s, ss
    stringmatha$ = s_var1$: stringmathb$ = s_var2$

    SELECT CASE operator$
        CASE "+", "-"
            GOSUB string_add_subtract_new
        CASE "*"
            GOSUB string_multiply_new
        CASE "/"
            GOSUB string_divide
        CASE ELSE
            PRINT "Error, no operator selected. operator$ = "; operator$: END
    END SELECT
    EXIT SUB

    string_divide:
    terminating_decimal% = 0: divsign% = 0: divremainder& = 0: divremainder$ = "": divplace& = 0: divplace2& = 0: quotient$ = "": divcarry& = 0
    divbuffer& = LEN(stringmathb$) - LEN(stringmatha$)
    IF divbuffer& < 0 THEN divbuffer& = 0
    d2dividend$ = stringmatha$
    d1divisor$ = stringmathb$
    IF LEFT$(d1divisor$, 1) = "0" AND LEN(d1divisor$) = 1 THEN PRINT "Division by zero not allowed.": divsign% = 0: EXIT SUB
    IF LEFT$(d1divisor$, 1) = "-" THEN divsign% = -1: d1divisor$ = MID$(d1divisor$, 2)
    IF LEFT$(d2dividend$, 1) = "-" THEN
        IF divsign% THEN
            divsign% = 0
        ELSE
            divsign% = -1
        END IF
        d2dividend$ = MID$(d2dividend$, 2)
    END IF
    IF INSTR(d1divisor$, ".") <> 0 THEN
        DO UNTIL RIGHT$(d1divisor$, 1) <> "0"
            d1divisor$ = MID$(d1divisor$, 1, LEN(d1divisor$) - 1) ' Strip off trailing zeros
        LOOP
        divplace& = LEN(d1divisor$) - INSTR(d1divisor$, ".")
        d1divisor$ = MID$(d1divisor$, 1, INSTR(d1divisor$, ".") - 1) + MID$(d1divisor$, INSTR(d1divisor$, ".") + 1) ' Strip off decimal point.
        DO UNTIL LEFT$(d1divisor$, 1) <> "0"
            d1divisor$ = MID$(d1divisor$, 2) ' Strip off leading zeros for divisors smaller than .1
        LOOP
    END IF

    IF INSTR(d2dividend$, ".") <> 0 THEN
        d2dividend$ = d2dividend$ + STRING$(divplace& - LEN(d2dividend$) - INSTR(d2dividend$, "."), "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace2& = INSTR(d2dividend$, ".")
        DO UNTIL RIGHT$(d2dividend$, 1) <> "0"
            d2dividend$ = MID$(d2dividend$, 1, LEN(d2dividend$) - 1) ' Strip off trailing zeros
        LOOP
        d2dividend$ = MID$(d2dividend$, 1, INSTR(d2dividend$, ".") - 1) + MID$(d2dividend$, INSTR(d2dividend$, ".") + 1) ' Strip off decimal point.
    ELSE
        d2dividend$ = d2dividend$ + STRING$(divplace&, "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace& = 0
    END IF
    DO
        DO
            divremainder& = divremainder& + 1: divremainder$ = divremainder$ + MID$(d2dividend$, divremainder&, 1)
            IF MID$(d2dividend$, divremainder&, 1) = "" THEN
                IF divremainder$ = STRING$(LEN(divremainder$), "0") AND LEN(quotient$) > LEN(d2dividend$) THEN
                    divflag% = -1
                    terminating_decimal% = -1
                    EXIT DO
                END IF
                divcarry& = divcarry& + 1
                IF divcarry& = 1 THEN divplace3& = divremainder& - 1
                IF divcarry& > limit&& + 1 + divbuffer& THEN
                    divflag% = -2: EXIT DO
                END IF
                divremainder$ = divremainder$ + "0" ' No more digits to bring down.
            END IF
            IF LEN(divremainder$) > LEN(d1divisor$) OR LEN(divremainder$) = LEN(d1divisor$) AND divremainder$ >= d1divisor$ THEN EXIT DO
            quotient$ = quotient$ + "0"
        LOOP
        IF divflag% THEN divflag% = 0: EXIT DO

        FOR div_i% = 9 TO 1 STEP -1
            stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
            GOSUB string_multiply_new ' Gets runningtotal$
            tempcutd$ = divremainder$ ' divremainder$ can be 00 or other leading zero values.
            DO
                IF LEN(tempcutd$) = 1 THEN EXIT DO
                IF LEFT$(tempcutd$, 1) = "0" THEN
                    tempcutd$ = MID$(tempcutd$, 2)
                ELSE
                    EXIT DO
                END IF
            LOOP
            IF LEN(tempcutd$) > LEN(runningtotal$) OR LEN(tempcutd$) = LEN(runningtotal$) AND runningtotal$ <= tempcutd$ THEN EXIT FOR
        NEXT
        quotient$ = quotient$ + LTRIM$(STR$(div_i%))
        stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
        GOSUB string_multiply_new ' Gets runningtotal$
        stringmatha$ = divremainder$: stringmathb$ = runningtotal$
        operator$ = "-": GOSUB string_add_subtract_new
        divremainder$ = runningtotal$
    LOOP

    IF divplace& = 0 AND divplace2& = 0 THEN divplace& = divplace3&
    IF divplace2& THEN divplace& = divplace& + divplace2& - 1
    IF quotient$ = "" THEN divplace& = 0 ' dividend is zero.
    IF divplace& OR divplace2& THEN
        quotient$ = MID$(quotient$, 1, divplace&) + "." + MID$(quotient$, divplace& + 1)
        DO UNTIL RIGHT$(quotient$, 1) <> "0"
            quotient$ = MID$(quotient$, 1, LEN(quotient$) - 1) ' Strip off trailing zeros
        LOOP
        IF RIGHT$(quotient$, 1) = "." THEN quotient$ = MID$(quotient$, 1, LEN(quotient$) - 1) ' Strip off abandoned decimal.
    END IF
    DO UNTIL LEFT$(quotient$, 1) <> "0"
        quotient$ = MID$(quotient$, 2) ' Strip off leading zeros
    LOOP
    IF quotient$ = "" THEN quotient$ = "0": divsign% = 0
    stringmathb$ = quotient$: quotient$ = ""

    IF stringmathb$ = "overflow" THEN divsign% = 0: EXIT SUB

    runningtotal$ = stringmathb$: stringmathb$ = ""
    IF divsign% THEN runningtotal$ = "-" + runningtotal$

    IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
    RETURN

    string_add_subtract_new:
    a1$ = stringmatha$: b1$ = stringmathb$
    s = 18: i&& = 0: c = 0

    a$ = stringmatha$: b$ = stringmathb$: op$ = operator$

    IF op$ = "-" THEN
        IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2) ELSE b$ = "-" + b$
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
        ' Line up decimal places by inserting trailing zeros.
        IF dec_b&& > dec_a&& THEN
            j&& = dec_b&&
            a$ = a$ + STRING$(dec_b&& - dec_a&&, "0")
        ELSE
            j&& = dec_a&&
            b$ = b$ + STRING$(dec_a&& - dec_b&&, "0")
        END IF
    END IF

    IF LEFT$(a$, 1) = "-" OR LEFT$(b$, 1) = "-" THEN
        IF LEFT$(a$, 1) = "-" AND LEFT$(b$, 1) = "-" THEN
            sign$ = "--": a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF LEFT$(a$, 1) = "-" THEN a$ = MID$(a$, 2): sign_a$ = "-"
            IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2): sign_b$ = "-"

            IF LEFT$(a1$, 1) = "-" THEN a1_x$ = MID$(a1$, 2) ELSE a1_x$ = a1$
            IF LEFT$(b1$, 1) = "-" THEN b1_x$ = MID$(b1$, 2) ELSE b1_x$ = b1$

            string_compare a1_x$, b1_x$, gl%

            IF gl% < 0 THEN
                IF LEN(sign_b$) THEN sign$ = "-": SWAP a$, b$
            ELSE
                IF LEN(sign_a$) THEN sign$ = "-": SWAP sign_a$, sign_b$
            END IF
        END IF
    END IF

    z$ = ""

    DO
        i&& = i&& + s
        x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
        x2$ = MID$(b$, LEN(b$) - i&& + 1, s)
        zeros% = LEN(x1$): IF LEN(x2$) > zeros% THEN zeros% = LEN(x2$)
        a = VAL(sign_a$ + x1$) + VAL(sign_b$ + x2$) + c
        IF x1$ + x2$ = "" AND c = 0 THEN EXIT DO
        c = 0
        IF a > VAL(STRING$(s, "9")) THEN a = a - 10 ^ s: c = 1
        IF a < 0 THEN a = a + 10 ^ s: c = -1
        tmp$ = LTRIM$(STR$(a))
        z$ = STRING$(zeros% - LEN(tmp$), "0") + tmp$ + z$
    LOOP

    IF decimal% THEN
        z$ = MID$(z$, 1, LEN(z$) - j&&) + "." + MID$(z$, LEN(z$) - j&& + 1)
    END IF

    ' Remove any leading zeros.
    DO
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ELSE EXIT DO
    LOOP

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = LEFT$(sign$, 1) + z$

    runningtotal$ = z$

    sign$ = "": sign_a$ = "": sign_b$ = "": i&& = 0: j&& = 0: decimal% = 0: c = 0
    RETURN

    string_multiply_new:
    z$ = "": sign$ = "": mult&& = 0: h&& = 0: i&& = 0: j&& = 0: c = 0: decimal% = 0
    zz$ = "": ii&& = 0: jj&& = 0
    s = 8: ss = 18

    a$ = stringmatha$: b$ = stringmathb$

    IF INSTR(a$, "-") <> 0 OR INSTR(b$, "-") <> 0 THEN
        IF INSTR(a$, "-") <> 0 AND INSTR(b$, "-") <> 0 THEN
            a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF INSTR(a$, "-") <> 0 THEN a$ = MID$(a$, 2) ELSE b$ = MID$(b$, 2)
            sign$ = "-"
        END IF
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
    END IF

    IF LEN(a$) < LEN(b$) THEN SWAP a$, b$ ' Needed so x1$ is always the largest for leading zero replacements.

    DO
        h&& = h&& + s: i&& = 0
        x2$ = MID$(b$, LEN(b$) - h&& + 1, s)
        WHILE -1
            i&& = i&& + s
            x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
            a = VAL(sign_a$ + x1$) * VAL(sign_b$ + x2$) + c
            c = 0
            tmp$ = LTRIM$(STR$(a))
            IF LEN(tmp$) > s THEN c = VAL(MID$(tmp$, 1, LEN(tmp$) - s)): tmp$ = MID$(tmp$, LEN(tmp$) - s + 1)
            z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
            IF i&& >= LEN(a$) AND c = 0 THEN EXIT WHILE
        WEND

        jj&& = jj&& + 1

        IF jj&& > 1 THEN
            ii&& = 0: cc = 0
            aa$ = holdaa$
            bb$ = z$ + STRING$((jj&& - 1) * s, "0")

            DO
                ii&& = ii&& + ss
                xx1$ = MID$(aa$, LEN(aa$) - ii&& + 1, ss)
                xx2$ = MID$(bb$, LEN(bb$) - ii&& + 1, ss)
                zeros% = LEN(xx1$): IF LEN(xx2$) > zeros% THEN zeros% = LEN(xx2$)
                aa = VAL(xx1$) + VAL(xx2$) + cc
                IF xx1$ + xx2$ = "" AND cc = 0 THEN EXIT DO ' Prevents leading zeros.
                cc = 0
                IF aa > VAL(STRING$(ss, "9")) THEN aa = aa - 10 ^ ss: cc = 1
                tmp$ = LTRIM$(STR$(aa))
                '''zz$ = STRING$(LEN(xx1$) - LEN(tmp$), "0") + tmp$ + zz$
                zz$ = STRING$(zeros% - LEN(tmp$), "0") + tmp$ + zz$
            LOOP

            DO WHILE LEFT$(zz$, 1) = "0"
                IF LEFT$(zz$, 1) = "0" THEN zz$ = MID$(zz$, 2)
            LOOP
            IF zz$ = "" THEN zz$ = "0"

            holdaa$ = zz$
        ELSE
            holdaa$ = z$ + STRING$(jj&& - 1, "0")
        END IF

        z$ = "": zz$ = ""

    LOOP UNTIL h&& >= LEN(b$)

    z$ = holdaa$

    IF decimal% THEN
        DO UNTIL LEN(z$) >= dec_a&& + dec_b&&
            z$ = "0" + z$
        LOOP

        z$ = MID$(z$, 0, LEN(z$) - (dec_a&& + dec_b&& - 1)) + "." + MID$(z$, LEN(z$) - (dec_a&& + dec_b&&) + 1)

        DO UNTIL RIGHT$(z$, 1) <> "0" AND RIGHT$(z$, 1) <> "."
            z$ = MID$(z$, 1, LEN(z$) - 1)
        LOOP
    END IF

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = sign$ + z$

    decimal% = 0: sign$ = ""

    runningtotal$ = z$
    RETURN
END SUB

SUB string_compare (compa$, compb$, gl%)
    DO
        ' Remove trailing zeros after a decimal point.
        IF INSTR(compa$, ".") THEN
            DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                compa$ = MID$(compa$, 1, LEN(compa$) - 1)
            LOOP
        END IF
        IF INSTR(compb$, ".") THEN
            DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                compb$ = MID$(compb$, 1, LEN(compb$) - 1)
            LOOP
        END IF

        IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
        IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

        ' A - and +
        IF LEFT$(compa$, 1) = "-" THEN j% = -1
        IF LEFT$(compb$, 1) = "-" THEN k% = -1
        IF k% = 0 AND j% THEN gl% = -1: EXIT DO
        IF j% = 0 AND k% THEN gl% = 1: EXIT DO

        ' A decimal and non-decimal.
        j% = INSTR(compa$, ".")
        k% = INSTR(compb$, ".")

        IF j% = 0 AND k% THEN
            IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
            EXIT DO
        END IF
        IF k% = 0 AND j% THEN
            IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
            EXIT DO
        END IF

        ' Both decimals.
        IF j% THEN
            IF compa$ > compb$ THEN
                gl% = 1
            ELSEIF compa$ = compb$ THEN gl% = 0
            ELSEIF compa$ < compb$ THEN gl% = -1
            END IF
            EXIT DO
        END IF

        ' Both positive or both negative whole numbers.
        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

SUB square_root (x$, sqrt$)
    oldy$ = "": sqrt$ = "": custom_limit&& = 200

    IF INSTR(x$, ".") THEN
        decx$ = MID$(x$, 1, INSTR(x$, ".") - 1)
        x$ = MID$(x$, 1, INSTR(x$, ".") - 1) + MID$(x$, INSTR(x$, ".") + 1)
        IF LEN(x$) = 1 THEN x$ = x$ + "0"
    ELSE
        decx$ = x$
    END IF

    j&& = LEN(decx$)

    ' VAL() okay, one character eval.
    IF VAL(RIGHT$(LTRIM$(STR$(j&&)), 1)) / 2 = VAL(RIGHT$(LTRIM$(STR$(j&&)), 1)) \ 2 THEN
        i&& = 1 ' Even number length.
    ELSE
        i&& = 0 ' Odd number length.
    END IF

    DO
        sm z$, "-", k$, runningtotal$
        z$ = runningtotal$ + (MID$(x$, i&&, 2))
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ' Remove leading zeros

        oldy$ = ""
        FOR j&& = 1 TO 10
            IF i&& > 1 THEN
                sm sqrt$, "*", "2", y$
                y$ = y$ + LTRIM$(STR$(j&&))
            ELSE
                y$ = LTRIM$(STR$(j&&))
            END IF

            sm y$, "*", LTRIM$(STR$(j&&)), runningtotal$

            string_compare runningtotal$, z$, gl%
            IF gl% > -1 THEN
                IF gl% = 0 THEN
                    h% = 0: oldy$ = y$ ' Perfect square division.
                ELSE
                    h% = 1
                END IF
                sm oldy$, "*", LTRIM$(STR$(j&& - h%)), runningtotal$

                IF STRING$(LEN(z$), "0") = z$ AND runningtotal$ = "0" AND i&& >= LEN(decx$) THEN EXIT DO

                IF dpx&& = 0 THEN ' Limited to && size unless converted to string.
                    IF i&& >= LEN(decx$) THEN
                        dpx&& = INT(LEN(decx$) / 2 + .5)
                        IF dpx&& = 0 THEN dpx&& = -1
                    END IF
                END IF

                IF betatest% < -1 THEN PRINT "Sqrt "; sqrt$; " * 2 = ";: COLOR 2, 0: PRINT LTRIM$(STR$(VAL(sqrt$) * 2));: COLOR 7, 0: PRINT LTRIM$(STR$(j&& - h%)); " * "; LTRIM$(STR$(j&& - h%)); " ="; VAL(oldy$) * (j&& - h%)
                sqrt$ = sqrt$ + LTRIM$(STR$(j&& - h%))

                sm oldy$, "*", LTRIM$(STR$(j&& - h%)), runningtotal$
                k$ = runningtotal$

                IF betatest% < -1 THEN PRINT "Remainder "; z$; " minus "; k$; " = ";
                EXIT FOR
            END IF
            oldy$ = y$
        NEXT

        i&& = i&& + 2
        IF LEN(z$) >= custom_limit&& THEN EXIT DO
        x$ = x$ + "00"
    LOOP

    IF dpx&& THEN
        sqrt$ = MID$(sqrt$, 0, dpx&& + 1) + "." + MID$(sqrt$, dpx&& + 1)
    END IF
END SUB


Pete
Reply
#26
Pete
if I set digits% to 100 then your program calculates Pi to about 154 decimals, in your previous version it would only give 51 correct decimals
I think that your precision tracking needs work
Reply
#27
(08-26-2022, 04:24 PM)Jack Wrote: Pete
if I set digits% to 100 then your program calculates Pi to about 154 decimals, in your previous version it would only give 51 correct decimals
I think that your precision tracking needs work

In the previous, somewhat different, version, I limited the output to the screen to 51 decimals. So that's about demo presentation, not precision.

I'm now looking into how particular statements slow down calculation loops. I found that setting a variable to the length of a small string, for some weird reason, makes a big noticeable difference in loop speed. Weird. I don't have enough testing yet to conclude why, or what could be used to speed things up. What I do know but don't want to get into now is considering what it would take to do fixed string replacement instead of string concatenation. That definitely increases speed, but it would need to be bullet-proof, meaning it must work in all possible conditions.

Pete
Reply
#28
Pete
I think the following was your previous version except that I changed limit&& and digits%, limit&& was 52 and digits% was 50, I also changed to console output
loop #13 is the last loop, loop #12 is accurate to 86 decimals
Quote:loop #12  pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628031244133064023
loop #13  pi = 3.141592704753823286968106636310008090364871048493655060239030000194318500280725372036486027296712004
Code: (Select All)
$Console:Only
_Dest _Console
Dim Shared digits%, limit&&, betatest%
limit&& = 102: betatest% = 0
Rem Jack's Ramanujan pi calculation algorithm with Pete's string math routine.
Dim As String n, m, c, sum, f, f4, f4k, c1, c2, c3, c34k, t1, t2, t3
Dim As Long k, k4
Dim t As Double

t = Timer
digits% = 100
c1 = "1103"
c2 = "26390"
c3 = "396"
f = "1"
f4k = "1"
sum = "1103"
c34k = "1"
k4 = 0
t1 = c3
t2 = c3
sm t1, "*", t2, c3
t1 = c3
t2 = c3
sm t1, "*", t2, c3

For k = 1 To digits% / 7.984
    t1 = f
    sm Str$(k), "*", t1, f
    If betatest% Then Print "results = "; f: Sleep
    t1 = f: t2 = f
    sm t1, "*", t2, f4
    If betatest% Then Print "results = "; f4: Sleep
    t1 = f4: t2 = f4
    sm t1, "*", t2, f4
    If betatest% Then Print "results = "; f4: Sleep
    t1 = c34k
    sm c3, "*", t1, c34k
    If betatest% Then Print "results = "; c34k: Sleep
    t1 = Str$(k4 + 1)
    t2 = f4k
    sm t1, "*", t2, f4k
    If betatest% Then Print "results = "; f4k: Sleep
    t1 = Str$(k4 + 2)
    t2 = f4k
    sm t1, "*", t2, f4k
    If betatest% Then Print "results = "; f4k: Sleep
    t1 = Str$(k4 + 3)
    t2 = f4k
    sm t1, "*", t2, f4k
    If betatest% Then Print "results = "; f4k: Sleep
    t1 = Str$(k4 + 4)
    t2 = f4k
    sm t1, "*", t2, f4k
    If betatest% Then Print "results = "; f4k: Sleep
    k4 = k4 + 4
    t1 = Str$(k)
    sm t1, "*", c2, t2
    If betatest% Then Print "results = "; t2: Sleep
    sm c1, "+", t2, t1
    If betatest% Then Print "results = "; t1: Sleep
    sm f4k, "*", t1, t2
    If betatest% Then Print "results = "; t2: Sleep
    sm f4, "*", c34k, t1
    If betatest% Then Print "results = "; t1: Sleep
    sm t2, "/", t1, t3
    If betatest% Then Print "results = "; t3: Sleep
    t1 = sum
    sm t1, "+", t3, sum
    If betatest% Then Print "sum =  "; sum: Sleep
    Call pi(t1, sum, k)
Next
Color 14, 0: Print "Ramanujan pi = 3.1415926535897932384626433832795028841971693993751"
Color 7, 0
t = Timer - t
Print: Print "Time:"; t
End

Sub pi (t1$, sum$, k)
    square_root "8", t1$
    If betatest% Then Print "Pi # = "; t1$: Sleep
    t2$ = "9801"
    sm t1$, "/", t2$, t3$
    If betatest% Then Print "Pi # = "; t3$: Sleep
    sm t3$, "*", sum$, t2$
    If betatest% Then Print "Pi # = "; t2$: Sleep
    sm t1$, "/", t2$, t3$
    If betatest% Then Print "Pi # = "; t3$: Sleep
    sm "1", "/", t2$, t1$
    If betatest% Then Print "Pi # = "; t1$: Sleep
    Print "loop #"; LTrim$(Str$(k));: Locate , 10: Print " pi = "; Mid$(t1$, 1, digits% + 1)
End Sub

Sub sm (s_var1$, operator$, s_var2$, runningtotal$)
    Dim As _Integer64 a, c, aa, cc, s, ss
    stringmatha$ = s_var1$: stringmathb$ = s_var2$

    Select Case operator$
        Case "+", "-"
            GoSub string_add_subtract_new
        Case "*"
            GoSub string_multiply_new
        Case "/"
            GoSub string_divide
        Case Else
            Print "Error, no operator selected. operator$ = "; operator$: End
    End Select
    Exit Sub

    string_divide:
    terminating_decimal% = 0: divsign% = 0: divremainder& = 0: divremainder$ = "": divplace& = 0: divplace2& = 0: quotient$ = "": divcarry& = 0
    divbuffer& = Len(stringmathb$) - Len(stringmatha$)
    If divbuffer& < 0 Then divbuffer& = 0
    d2dividend$ = stringmatha$
    d1divisor$ = stringmathb$
    If Left$(d1divisor$, 1) = "0" And Len(d1divisor$) = 1 Then Print "Division by zero not allowed.": divsign% = 0: Exit Sub
    If Left$(d1divisor$, 1) = "-" Then divsign% = -1: d1divisor$ = Mid$(d1divisor$, 2)
    If Left$(d2dividend$, 1) = "-" Then
        If divsign% Then
            divsign% = 0
        Else
            divsign% = -1
        End If
        d2dividend$ = Mid$(d2dividend$, 2)
    End If
    If InStr(d1divisor$, ".") <> 0 Then
        Do Until Right$(d1divisor$, 1) <> "0"
            d1divisor$ = Mid$(d1divisor$, 1, Len(d1divisor$) - 1) ' Strip off trailing zeros
        Loop
        divplace& = Len(d1divisor$) - InStr(d1divisor$, ".")
        d1divisor$ = Mid$(d1divisor$, 1, InStr(d1divisor$, ".") - 1) + Mid$(d1divisor$, InStr(d1divisor$, ".") + 1) ' Strip off decimal point.
        Do Until Left$(d1divisor$, 1) <> "0"
            d1divisor$ = Mid$(d1divisor$, 2) ' Strip off leading zeros for divisors smaller than .1
        Loop
    End If

    If InStr(d2dividend$, ".") <> 0 Then
        d2dividend$ = d2dividend$ + String$(divplace& - Len(d2dividend$) - InStr(d2dividend$, "."), "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace2& = InStr(d2dividend$, ".")
        Do Until Right$(d2dividend$, 1) <> "0"
            d2dividend$ = Mid$(d2dividend$, 1, Len(d2dividend$) - 1) ' Strip off trailing zeros
        Loop
        d2dividend$ = Mid$(d2dividend$, 1, InStr(d2dividend$, ".") - 1) + Mid$(d2dividend$, InStr(d2dividend$, ".") + 1) ' Strip off decimal point.
    Else
        d2dividend$ = d2dividend$ + String$(divplace&, "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace& = 0
    End If
    Do
        Do
            divremainder& = divremainder& + 1: divremainder$ = divremainder$ + Mid$(d2dividend$, divremainder&, 1)
            If Mid$(d2dividend$, divremainder&, 1) = "" Then
                If divremainder$ = String$(Len(divremainder$), "0") And Len(quotient$) > Len(d2dividend$) Then
                    divflag% = -1
                    terminating_decimal% = -1
                    Exit Do
                End If
                divcarry& = divcarry& + 1
                If divcarry& = 1 Then divplace3& = divremainder& - 1
                If divcarry& > limit&& + 1 + divbuffer& Then
                    divflag% = -2: Exit Do
                End If
                divremainder$ = divremainder$ + "0" ' No more digits to bring down.
            End If
            If Len(divremainder$) > Len(d1divisor$) Or Len(divremainder$) = Len(d1divisor$) And divremainder$ >= d1divisor$ Then Exit Do
            quotient$ = quotient$ + "0"
        Loop
        If divflag% Then divflag% = 0: Exit Do

        For div_i% = 9 To 1 Step -1
            stringmatha$ = LTrim$(Str$(div_i%)): stringmathb$ = d1divisor$
            GoSub string_multiply_new ' Gets runningtotal$
            tempcutd$ = divremainder$ ' divremainder$ can be 00 or other leading zero values.
            Do
                If Len(tempcutd$) = 1 Then Exit Do
                If Left$(tempcutd$, 1) = "0" Then
                    tempcutd$ = Mid$(tempcutd$, 2)
                Else
                    Exit Do
                End If
            Loop
            If Len(tempcutd$) > Len(runningtotal$) Or Len(tempcutd$) = Len(runningtotal$) And runningtotal$ <= tempcutd$ Then Exit For
        Next
        quotient$ = quotient$ + LTrim$(Str$(div_i%))
        stringmatha$ = LTrim$(Str$(div_i%)): stringmathb$ = d1divisor$
        GoSub string_multiply_new ' Gets runningtotal$
        stringmatha$ = divremainder$: stringmathb$ = runningtotal$
        operator$ = "-": GoSub string_add_subtract_new
        divremainder$ = runningtotal$
    Loop

    If divplace& = 0 And divplace2& = 0 Then divplace& = divplace3&
    If divplace2& Then divplace& = divplace& + divplace2& - 1
    If quotient$ = "" Then divplace& = 0 ' dividend is zero.
    If divplace& Or divplace2& Then
        quotient$ = Mid$(quotient$, 1, divplace&) + "." + Mid$(quotient$, divplace& + 1)
        Do Until Right$(quotient$, 1) <> "0"
            quotient$ = Mid$(quotient$, 1, Len(quotient$) - 1) ' Strip off trailing zeros
        Loop
        If Right$(quotient$, 1) = "." Then quotient$ = Mid$(quotient$, 1, Len(quotient$) - 1) ' Strip off abandoned decimal.
    End If
    Do Until Left$(quotient$, 1) <> "0"
        quotient$ = Mid$(quotient$, 2) ' Strip off leading zeros
    Loop
    If quotient$ = "" Then quotient$ = "0": divsign% = 0
    stringmathb$ = quotient$: quotient$ = ""

    If stringmathb$ = "overflow" Then divsign% = 0: Exit Sub

    runningtotal$ = stringmathb$: stringmathb$ = ""
    If divsign% Then runningtotal$ = "-" + runningtotal$

    If stringmathround$ <> "" Then runningtotal$ = runningtotal$ + stringmathround$
    Return

    string_add_subtract_new:
    a1$ = stringmatha$: b1$ = stringmathb$
    s = 18: i&& = 0: c = 0

    a$ = stringmatha$: b$ = stringmathb$: op$ = operator$

    If op$ = "-" Then
        If Left$(b$, 1) = "-" Then b$ = Mid$(b$, 2) Else b$ = "-" + b$
    End If

    If InStr(a$, ".") <> 0 Or InStr(b$, ".") <> 0 Then
        decimal% = -1
        If InStr(a$, ".") <> 0 Then
            dec_a&& = Len(Mid$(a$, InStr(a$, ".") + 1))
            a$ = Mid$(a$, 1, InStr(a$, ".") - 1) + Mid$(a$, InStr(a$, ".") + 1)
        End If
        If InStr(b$, ".") <> 0 Then
            dec_b&& = Len(Mid$(b$, InStr(b$, ".") + 1))
            b$ = Mid$(b$, 1, InStr(b$, ".") - 1) + Mid$(b$, InStr(b$, ".") + 1)
        End If
        ' Line up decimal places by inserting trailing zeros.
        If dec_b&& > dec_a&& Then
            j&& = dec_b&&
            a$ = a$ + String$(dec_b&& - dec_a&&, "0")
        Else
            j&& = dec_a&&
            b$ = b$ + String$(dec_a&& - dec_b&&, "0")
        End If
    End If

    If Left$(a$, 1) = "-" Or Left$(b$, 1) = "-" Then
        If Left$(a$, 1) = "-" And Left$(b$, 1) = "-" Then
            sign$ = "--": a$ = Mid$(a$, 2): b$ = Mid$(b$, 2)
        Else
            If Left$(a$, 1) = "-" Then a$ = Mid$(a$, 2): sign_a$ = "-"
            If Left$(b$, 1) = "-" Then b$ = Mid$(b$, 2): sign_b$ = "-"

            If Left$(a1$, 1) = "-" Then a1_x$ = Mid$(a1$, 2) Else a1_x$ = a1$
            If Left$(b1$, 1) = "-" Then b1_x$ = Mid$(b1$, 2) Else b1_x$ = b1$

            string_compare a1_x$, b1_x$, gl%

            If gl% < 0 Then
                If Len(sign_b$) Then sign$ = "-": Swap a$, b$
            Else
                If Len(sign_a$) Then sign$ = "-": Swap sign_a$, sign_b$
            End If
        End If
    End If

    z$ = ""

    Do
        i&& = i&& + s
        x1$ = Mid$(a$, Len(a$) - i&& + 1, s)
        x2$ = Mid$(b$, Len(b$) - i&& + 1, s)
        zeros% = Len(x1$): If Len(x2$) > zeros% Then zeros% = Len(x2$)
        a = Val(sign_a$ + x1$) + Val(sign_b$ + x2$) + c
        If x1$ + x2$ = "" And c = 0 Then Exit Do
        c = 0
        If a > Val(String$(s, "9")) Then a = a - 10 ^ s: c = 1
        If a < 0 Then a = a + 10 ^ s: c = -1
        tmp$ = LTrim$(Str$(a))
        z$ = String$(zeros% - Len(tmp$), "0") + tmp$ + z$
    Loop

    If decimal% Then
        z$ = Mid$(z$, 1, Len(z$) - j&&) + "." + Mid$(z$, Len(z$) - j&& + 1)
    End If

    ' Remove any leading zeros.
    Do
        If Left$(z$, 1) = "0" Then z$ = Mid$(z$, 2) Else Exit Do
    Loop

    If z$ = "" Or z$ = "0" Then z$ = "0" Else z$ = Left$(sign$, 1) + z$

    runningtotal$ = z$

    sign$ = "": sign_a$ = "": sign_b$ = "": i&& = 0: j&& = 0: decimal% = 0: c = 0
    Return

    string_multiply_new:
    z$ = "": sign$ = "": mult&& = 0: h&& = 0: i&& = 0: j&& = 0: c = 0: decimal% = 0
    zz$ = "": ii&& = 0: jj&& = 0
    s = 8: ss = 18

    a$ = stringmatha$: b$ = stringmathb$

    If InStr(a$, "-") <> 0 Or InStr(b$, "-") <> 0 Then
        If InStr(a$, "-") <> 0 And InStr(b$, "-") <> 0 Then
            a$ = Mid$(a$, 2): b$ = Mid$(b$, 2)
        Else
            If InStr(a$, "-") <> 0 Then a$ = Mid$(a$, 2) Else b$ = Mid$(b$, 2)
            sign$ = "-"
        End If
    End If

    If InStr(a$, ".") <> 0 Or InStr(b$, ".") <> 0 Then
        decimal% = -1
        If InStr(a$, ".") <> 0 Then
            dec_a&& = Len(Mid$(a$, InStr(a$, ".") + 1))
            a$ = Mid$(a$, 1, InStr(a$, ".") - 1) + Mid$(a$, InStr(a$, ".") + 1)
        End If
        If InStr(b$, ".") <> 0 Then
            dec_b&& = Len(Mid$(b$, InStr(b$, ".") + 1))
            b$ = Mid$(b$, 1, InStr(b$, ".") - 1) + Mid$(b$, InStr(b$, ".") + 1)
        End If
    End If

    If Len(a$) < Len(b$) Then Swap a$, b$ ' Needed so x1$ is always the largest for leading zero replacements.

    Do
        h&& = h&& + s: i&& = 0
        x2$ = Mid$(b$, Len(b$) - h&& + 1, s)
        While -1
            i&& = i&& + s
            x1$ = Mid$(a$, Len(a$) - i&& + 1, s)
            a = Val(sign_a$ + x1$) * Val(sign_b$ + x2$) + c
            c = 0
            tmp$ = LTrim$(Str$(a))
            If Len(tmp$) > s Then c = Val(Mid$(tmp$, 1, Len(tmp$) - s)): tmp$ = Mid$(tmp$, Len(tmp$) - s + 1)
            z$ = String$(Len(x1$) - Len(tmp$), "0") + tmp$ + z$
            If i&& >= Len(a$) And c = 0 Then Exit While
        Wend

        jj&& = jj&& + 1

        If jj&& > 1 Then
            ii&& = 0: cc = 0
            aa$ = holdaa$
            bb$ = z$ + String$((jj&& - 1) * s, "0")

            Do
                ii&& = ii&& + ss
                xx1$ = Mid$(aa$, Len(aa$) - ii&& + 1, ss)
                xx2$ = Mid$(bb$, Len(bb$) - ii&& + 1, ss)
                aa = Val(xx1$) + Val(xx2$) + cc
                If xx1$ + xx2$ = "" And cc = 0 Then Exit Do ' Prevents leading zeros.
                cc = 0
                If aa > Val(String$(ss, "9")) Then aa = aa - 10 ^ ss: cc = 1
                tmp$ = LTrim$(Str$(aa))
                zz$ = String$(Len(xx1$) - Len(tmp$), "0") + tmp$ + zz$
            Loop

            Do While Left$(zz$, 1) = "0"
                If Left$(zz$, 1) = "0" Then zz$ = Mid$(zz$, 2)
            Loop
            If zz$ = "" Then zz$ = "0"

            holdaa$ = zz$
        Else
            holdaa$ = z$ + String$(jj&& - 1, "0")
        End If

        z$ = "": zz$ = ""

    Loop Until h&& >= Len(b$)

    z$ = holdaa$

    If decimal% Then
        Do Until Len(z$) >= dec_a&& + dec_b&&
            z$ = "0" + z$
        Loop

        z$ = Mid$(z$, 0, Len(z$) - (dec_a&& + dec_b&& - 1)) + "." + Mid$(z$, Len(z$) - (dec_a&& + dec_b&&) + 1)

        Do Until Right$(z$, 1) <> "0" And Right$(z$, 1) <> "."
            z$ = Mid$(z$, 1, Len(z$) - 1)
        Loop
    End If

    If z$ = "" Or z$ = "0" Then z$ = "0" Else z$ = sign$ + z$

    decimal% = 0: sign$ = ""

    runningtotal$ = z$
    Return
End Sub

Sub string_compare (compa$, compb$, gl%)
    Do
        ' Remove trailing zeros after a decimal point.
        If InStr(compa$, ".") Then
            Do Until Right$(compa$, 1) <> "0" And Right$(compa$, 1) <> "." And Right$(compa$, 1) <> "-"
                compa$ = Mid$(compa$, 1, Len(compa$) - 1)
            Loop
        End If
        If InStr(compb$, ".") Then
            Do Until Right$(compb$, 1) <> "0" And Right$(compb$, 1) <> "." And Right$(compb$, 1) <> "-"
                compb$ = Mid$(compb$, 1, Len(compb$) - 1)
            Loop
        End If

        If Mid$(compa$, 1, 2) = "-0" Or compa$ = "" Or compa$ = "-" Then compa$ = "0"
        If Mid$(compb$, 1, 2) = "-0" Or compb$ = "" Or compb$ = "-" Then compb$ = "0"

        ' A - and +
        If Left$(compa$, 1) = "-" Then j% = -1
        If Left$(compb$, 1) = "-" Then k% = -1
        If k% = 0 And j% Then gl% = -1: Exit Do
        If j% = 0 And k% Then gl% = 1: Exit Do

        ' A decimal and non-decimal.
        j% = InStr(compa$, ".")
        k% = InStr(compb$, ".")

        If j% = 0 And k% Then
            If compa$ = "0" Then gl% = -1 Else gl% = 1
            Exit Do
        End If
        If k% = 0 And j% Then
            If compb$ = "0" Then gl% = 1 Else gl% = -1
            Exit Do
        End If

        ' Both decimals.
        If j% Then
            If compa$ > compb$ Then
                gl% = 1
            ElseIf compa$ = compb$ Then gl% = 0
            ElseIf compa$ < compb$ Then gl% = -1
            End If
            Exit Do
        End If

        ' Both positive or both negative whole numbers.
        Select Case Len(compa$)
            Case Is < Len(compb$)
                gl% = -1
            Case Is = Len(compb$)
                If compa$ = compb$ Then
                    gl% = 0
                ElseIf compa$ > compb$ Then gl% = 1
                ElseIf compa$ < compb$ Then gl% = -1
                End If
            Case Is > Len(compb$)
                gl% = 1
        End Select
        Exit Do
    Loop
End Sub

Sub square_root (x$, sqrt$)
    oldy$ = "": sqrt$ = ""

    If InStr(x$, ".") Then
        decx$ = Mid$(x$, 1, InStr(x$, ".") - 1)
        x$ = Mid$(x$, 1, InStr(x$, ".") - 1) + Mid$(x$, InStr(x$, ".") + 1)
        If Len(x$) = 1 Then x$ = x$ + "0"
    Else
        decx$ = x$
    End If

    j&& = Len(decx$)

    ' VAL() okay, one character eval.
    If Val(Right$(LTrim$(Str$(j&&)), 1)) / 2 = Val(Right$(LTrim$(Str$(j&&)), 1)) \ 2 Then
        i&& = 1 ' Even number length.
    Else
        i&& = 0 ' Odd number length.
    End If

    Do
        sm z$, "-", k$, runningtotal$
        z$ = runningtotal$ + (Mid$(x$, i&&, 2))
        If Left$(z$, 1) = "0" Then z$ = Mid$(z$, 2) ' Remove leading zeros

        oldy$ = ""
        For j&& = 1 To 10
            If i&& > 1 Then
                sm sqrt$, "*", "2", y$
                y$ = y$ + LTrim$(Str$(j&&))
            Else
                y$ = LTrim$(Str$(j&&))
            End If

            sm y$, "*", LTrim$(Str$(j&&)), runningtotal$

            string_compare runningtotal$, z$, gl%
            If gl% > -1 Then
                If gl% = 0 Then
                    h% = 0: oldy$ = y$ ' Perfect square division.
                Else
                    h% = 1
                End If
                sm oldy$, "*", LTrim$(Str$(j&& - h%)), runningtotal$

                If String$(Len(z$), "0") = z$ And runningtotal$ = "0" And i&& >= Len(decx$) Then Exit Do

                If dpx&& = 0 Then ' Limited to && size unless converted to string.
                    If i&& >= Len(decx$) Then
                        dpx&& = Int(Len(decx$) / 2 + .5)
                        If dpx&& = 0 Then dpx&& = -1
                    End If
                End If

                If betatest% Then Print "Sqrt "; sqrt$; " * 2 = ";: Color 2, 0: Print LTrim$(Str$(Val(sqrt$) * 2));: Color 7, 0: Print LTrim$(Str$(j&& - h%)); " * "; LTrim$(Str$(j&& - h%)); " ="; Val(oldy$) * (j&& - h%)
                sqrt$ = sqrt$ + LTrim$(Str$(j&& - h%))

                sm oldy$, "*", LTrim$(Str$(j&& - h%)), runningtotal$
                k$ = runningtotal$

                If betatest% Then Print "Remainder "; z$; " minus "; k$; " = ";
                Exit For
            End If
            oldy$ = y$
        Next

        i&& = i&& + 2
        If Len(z$) >= limit&& Then Exit Do
        x$ = x$ + "00"
    Loop

    If dpx&& Then
        sqrt$ = Mid$(sqrt$, 0, dpx&& + 1) + "." + Mid$(sqrt$, dpx&& + 1)
    End If
End Sub
Reply
#29
That older version had a bug in the loop that followed: IF jj&& > 1 THEN

The latest version works, so far, as tested. Post #25 https://qb64phoenix.com/forum/showthread...25#pid5825

Pete
Reply
#30
@Jack

This is the latest update, made for console display, which allows scrolling to see all the results.

I haven't found a tweak yet that would make it process faster than the one using Treebeard's string math, but his routine would need to have the too small of a SQR(8) situation addressed, which is easy.

Code: (Select All)
$CONSOLE:ONLY
_DEST _CONSOLE
DIM SHARED sqrt$, limit&&, betatest%
betatest% = 0
DIM AS STRING n, m, c, sum, f, f4, f4k, c1, c2, c3, c34k, t1, t2, t3
DIM AS LONG k, k4
DIM t AS DOUBLE

limit&& = 200: square_root "8", sqrt$ ' Limit must be as many or more digits than the max digits of the returned value for pi.

FOR pete% = 0 TO 16
    digits% = pete% + 10 + pete% * 8
    limit&& = digits% + 7
    t = TIMER
    c1 = "1103"
    c2 = "26390"
    c3 = "396"
    f = "1"
    f4k = "1"
    sum = "1103"
    c34k = "1"
    k4 = 0
    t1 = c3
    t2 = c3
    sm t1, "*", t2, c3
    t1 = c3
    t2 = c3
    sm t1, "*", t2, c3

    FOR k = 1 TO digits% / (7.984)
        t1 = f
        sm STR$(k), "*", t1, f
        IF betatest% THEN PRINT "results = "; f: SLEEP
        t1 = f: t2 = f
        sm t1, "*", t2, f4
        IF betatest% THEN PRINT "results = "; f4: SLEEP
        t1 = f4: t2 = f4
        sm t1, "*", t2, f4
        IF betatest% THEN PRINT "results = "; f4: SLEEP
        t1 = c34k
        sm c3, "*", t1, c34k
        IF betatest% THEN PRINT "results = "; c34k: SLEEP
        t1 = STR$(k4 + 1)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 2)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 3)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        t1 = STR$(k4 + 4)
        t2 = f4k
        sm t1, "*", t2, f4k
        IF betatest% THEN PRINT "results = "; f4k: SLEEP
        k4 = k4 + 4
        t1 = STR$(k)
        sm t1, "*", c2, t2
        IF betatest% THEN PRINT "results = "; t2: SLEEP
        sm c1, "+", t2, t1
        IF betatest% THEN PRINT "results = "; t1: SLEEP
        sm f4k, "*", t1, t2
        IF betatest% THEN PRINT "results = "; t2: SLEEP
        sm f4, "*", c34k, t1
        IF betatest% THEN PRINT "results = "; t1: SLEEP
        sm t2, "/", t1, t3
        IF betatest% THEN PRINT "results = "; t3: SLEEP
        t1 = sum
        sm t1, "+", t3, sum
        IF betatest% THEN PRINT "sum =   "; sum: SLEEP
        CALL pi(t1, sum, k)
    NEXT
    COLOR 14, 0: PRINT "Ramanujan pi = "; MID$("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481", 1, 11 + (k - 2) * 8)
    COLOR 7, 0
    t = TIMER - t
    PRINT "Time:"; t: PRINT
NEXT pete%
END

SUB pi (t1$, sum$, k)
    REM square_root "8", sqrt$
    IF betatest% THEN PRINT "Pi # = "; sqrt$: SLEEP
    t2$ = "9801"
    sm sqrt$, "/", t2$, t3$
    IF betatest% THEN PRINT "Pi # = "; t3$: SLEEP
    sm t3$, "*", sum$, t2$
    IF betatest% THEN PRINT "Pi # = "; t2$: SLEEP
    sm t1$, "/", t2$, t3$
    IF betatest% THEN PRINT "Pi # = "; t3$: SLEEP
    sm "1", "/", t2$, t1$
    IF betatest% THEN PRINT "Pi # = "; t1$: SLEEP
    PRINT "loop #"; LTRIM$(STR$(k));: LOCATE , 10: PRINT " pi = "; MID$(t1$, 1, 11 + (k - 1) * 8);: COLOR 8, 0: PRINT MID$(t1$, 11 + (k - 1) * 8 + 1, 4): COLOR 7, 0
END SUB

SUB sm (s_var1$, operator$, s_var2$, runningtotal$)
    DIM AS _INTEGER64 a, c, aa, cc, s, ss
    stringmatha$ = s_var1$: stringmathb$ = s_var2$

    SELECT CASE operator$
        CASE "+", "-"
            GOSUB string_add_subtract_new
        CASE "*"
            GOSUB string_multiply_new
        CASE "/"
            GOSUB string_divide
        CASE ELSE
            PRINT "Error, no operator selected. operator$ = "; operator$: END
    END SELECT
    EXIT SUB

    string_divide:
    terminating_decimal% = 0: divsign% = 0: divremainder& = 0: divremainder$ = "": divplace& = 0: divplace2& = 0: quotient$ = "": divcarry& = 0
    divbuffer& = LEN(stringmathb$) - LEN(stringmatha$)
    IF divbuffer& < 0 THEN divbuffer& = 0
    d2dividend$ = stringmatha$
    d1divisor$ = stringmathb$
    IF LEFT$(d1divisor$, 1) = "0" AND LEN(d1divisor$) = 1 THEN PRINT "Division by zero not allowed.": divsign% = 0: EXIT SUB
    IF LEFT$(d1divisor$, 1) = "-" THEN divsign% = -1: d1divisor$ = MID$(d1divisor$, 2)
    IF LEFT$(d2dividend$, 1) = "-" THEN
        IF divsign% THEN
            divsign% = 0
        ELSE
            divsign% = -1
        END IF
        d2dividend$ = MID$(d2dividend$, 2)
    END IF
    IF INSTR(d1divisor$, ".") <> 0 THEN
        DO UNTIL RIGHT$(d1divisor$, 1) <> "0"
            d1divisor$ = MID$(d1divisor$, 1, LEN(d1divisor$) - 1) ' Strip off trailing zeros
        LOOP
        divplace& = LEN(d1divisor$) - INSTR(d1divisor$, ".")
        d1divisor$ = MID$(d1divisor$, 1, INSTR(d1divisor$, ".") - 1) + MID$(d1divisor$, INSTR(d1divisor$, ".") + 1) ' Strip off decimal point.
        DO UNTIL LEFT$(d1divisor$, 1) <> "0"
            d1divisor$ = MID$(d1divisor$, 2) ' Strip off leading zeros for divisors smaller than .1
        LOOP
    END IF

    IF INSTR(d2dividend$, ".") <> 0 THEN
        d2dividend$ = d2dividend$ + STRING$(divplace& - LEN(d2dividend$) - INSTR(d2dividend$, "."), "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace2& = INSTR(d2dividend$, ".")
        DO UNTIL RIGHT$(d2dividend$, 1) <> "0"
            d2dividend$ = MID$(d2dividend$, 1, LEN(d2dividend$) - 1) ' Strip off trailing zeros
        LOOP
        d2dividend$ = MID$(d2dividend$, 1, INSTR(d2dividend$, ".") - 1) + MID$(d2dividend$, INSTR(d2dividend$, ".") + 1) ' Strip off decimal point.
    ELSE
        d2dividend$ = d2dividend$ + STRING$(divplace&, "0") ' Add any zeros based on the length of dividend at decimal - length of divisor at decimal. If less than zero, nothing added.
        divplace& = 0
    END IF
    DO
        DO
            divremainder& = divremainder& + 1: divremainder$ = divremainder$ + MID$(d2dividend$, divremainder&, 1)
            IF MID$(d2dividend$, divremainder&, 1) = "" THEN
                IF divremainder$ = STRING$(LEN(divremainder$), "0") AND LEN(quotient$) > LEN(d2dividend$) THEN
                    divflag% = -1
                    terminating_decimal% = -1
                    EXIT DO
                END IF
                divcarry& = divcarry& + 1
                IF divcarry& = 1 THEN divplace3& = divremainder& - 1
                IF divcarry& > limit&& + 1 + divbuffer& THEN
                    divflag% = -2: EXIT DO
                END IF
                divremainder$ = divremainder$ + "0" ' No more digits to bring down.
            END IF
            IF LEN(divremainder$) > LEN(d1divisor$) OR LEN(divremainder$) = LEN(d1divisor$) AND divremainder$ >= d1divisor$ THEN EXIT DO
            quotient$ = quotient$ + "0"
        LOOP
        IF divflag% THEN divflag% = 0: EXIT DO

        FOR div_i% = 9 TO 1 STEP -1
            stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
            GOSUB string_multiply_new ' Gets runningtotal$
            tempcutd$ = divremainder$ ' divremainder$ can be 00 or other leading zero values.
            DO
                IF LEN(tempcutd$) = 1 THEN EXIT DO
                IF LEFT$(tempcutd$, 1) = "0" THEN
                    tempcutd$ = MID$(tempcutd$, 2)
                ELSE
                    EXIT DO
                END IF
            LOOP
            IF LEN(tempcutd$) > LEN(runningtotal$) OR LEN(tempcutd$) = LEN(runningtotal$) AND runningtotal$ <= tempcutd$ THEN EXIT FOR
        NEXT
        quotient$ = quotient$ + LTRIM$(STR$(div_i%))
        stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
        GOSUB string_multiply_new ' Gets runningtotal$
        stringmatha$ = divremainder$: stringmathb$ = runningtotal$
        operator$ = "-": GOSUB string_add_subtract_new
        divremainder$ = runningtotal$
    LOOP

    IF divplace& = 0 AND divplace2& = 0 THEN divplace& = divplace3&
    IF divplace2& THEN divplace& = divplace& + divplace2& - 1
    IF quotient$ = "" THEN divplace& = 0 ' dividend is zero.
    IF divplace& OR divplace2& THEN
        quotient$ = MID$(quotient$, 1, divplace&) + "." + MID$(quotient$, divplace& + 1)
        DO UNTIL RIGHT$(quotient$, 1) <> "0"
            quotient$ = MID$(quotient$, 1, LEN(quotient$) - 1) ' Strip off trailing zeros
        LOOP
        IF RIGHT$(quotient$, 1) = "." THEN quotient$ = MID$(quotient$, 1, LEN(quotient$) - 1) ' Strip off abandoned decimal.
    END IF
    DO UNTIL LEFT$(quotient$, 1) <> "0"
        quotient$ = MID$(quotient$, 2) ' Strip off leading zeros
    LOOP
    IF quotient$ = "" THEN quotient$ = "0": divsign% = 0
    stringmathb$ = quotient$: quotient$ = ""

    IF stringmathb$ = "overflow" THEN divsign% = 0: EXIT SUB

    runningtotal$ = stringmathb$: stringmathb$ = ""
    IF divsign% THEN runningtotal$ = "-" + runningtotal$

    IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
    RETURN

    string_add_subtract_new:
    a1$ = stringmatha$: b1$ = stringmathb$
    s = 18: i&& = 0: c = 0

    a$ = stringmatha$: b$ = stringmathb$: op$ = operator$

    IF op$ = "-" THEN
        IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2) ELSE b$ = "-" + b$
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
        ' Line up decimal places by inserting trailing zeros.
        IF dec_b&& > dec_a&& THEN
            j&& = dec_b&&
            a$ = a$ + STRING$(dec_b&& - dec_a&&, "0")
        ELSE
            j&& = dec_a&&
            b$ = b$ + STRING$(dec_a&& - dec_b&&, "0")
        END IF
    END IF

    IF LEFT$(a$, 1) = "-" OR LEFT$(b$, 1) = "-" THEN
        IF LEFT$(a$, 1) = "-" AND LEFT$(b$, 1) = "-" THEN
            sign$ = "--": a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF LEFT$(a$, 1) = "-" THEN a$ = MID$(a$, 2): sign_a$ = "-"
            IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2): sign_b$ = "-"

            IF LEFT$(a1$, 1) = "-" THEN a1_x$ = MID$(a1$, 2) ELSE a1_x$ = a1$
            IF LEFT$(b1$, 1) = "-" THEN b1_x$ = MID$(b1$, 2) ELSE b1_x$ = b1$

            string_compare a1_x$, b1_x$, gl%

            IF gl% < 0 THEN
                IF LEN(sign_b$) THEN sign$ = "-": SWAP a$, b$
            ELSE
                IF LEN(sign_a$) THEN sign$ = "-": SWAP sign_a$, sign_b$
            END IF
        END IF
    END IF

    z$ = ""
    ' Addition and subtraction of digits.
    DO
        i&& = i&& + s
        x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
        x2$ = MID$(b$, LEN(b$) - i&& + 1, s)
        zeros% = LEN(x1$): IF LEN(x2$) > zeros% THEN zeros% = LEN(x2$)
        a = VAL(sign_a$ + x1$) + VAL(sign_b$ + x2$) + c
        IF x1$ + x2$ = "" AND c = 0 THEN EXIT DO
        c = 0
        IF a > VAL(STRING$(s, "9")) THEN a = a - 10 ^ s: c = 1
        IF a < 0 THEN a = a + 10 ^ s: c = -1 ' a will never be less than 0.
        tmp$ = LTRIM$(STR$(a))
        z$ = STRING$(zeros% - LEN(tmp$), "0") + tmp$ + z$
    LOOP

    IF decimal% THEN
        z$ = MID$(z$, 1, LEN(z$) - j&&) + "." + MID$(z$, LEN(z$) - j&& + 1)
    END IF

    ' Remove any leading zeros.
    DO
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ELSE EXIT DO
    LOOP

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = LEFT$(sign$, 1) + z$

    runningtotal$ = z$

    sign$ = "": sign_a$ = "": sign_b$ = "": i&& = 0: j&& = 0: decimal% = 0: c = 0
    RETURN

    string_multiply_new:
    z$ = "": sign$ = "": mult&& = 0: h&& = 0: i&& = 0: j&& = 0: c = 0: decimal% = 0
    zz$ = "": ii&& = 0: jj&& = 0
    s = 8: ss = 18

    a$ = stringmatha$: b$ = stringmathb$

    IF INSTR(a$, "-") <> 0 OR INSTR(b$, "-") <> 0 THEN
        IF INSTR(a$, "-") <> 0 AND INSTR(b$, "-") <> 0 THEN
            a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF INSTR(a$, "-") <> 0 THEN a$ = MID$(a$, 2) ELSE b$ = MID$(b$, 2)
            sign$ = "-"
        END IF
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
    END IF

    IF LEN(a$) < LEN(b$) THEN SWAP a$, b$ ' Needed so x1$ is always the largest for leading zero replacements.
    ' Multiplication of digits.
    DO
        h&& = h&& + s: i&& = 0
        x2$ = MID$(b$, LEN(b$) - h&& + 1, s)
        DO
            i&& = i&& + s
            x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
            a = VAL(x1$) * VAL(x2$) + c
            c = 0
            tmp$ = LTRIM$(STR$(a))
            IF LEN(tmp$) > s THEN c = VAL(MID$(tmp$, 1, LEN(tmp$) - s)): tmp$ = MID$(tmp$, LEN(tmp$) - s + 1)
            z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
        LOOP UNTIL i&& >= LEN(a$) AND c = 0

        jj&& = jj&& + 1

        IF jj&& > 1 THEN
            ii&& = 0: cc = 0
            aa$ = holdaa$
            bb$ = z$ + STRING$((jj&& - 1) * s, "0")
            ' Addition only of digits.
            DO
                ii&& = ii&& + ss
                xx1$ = MID$(aa$, LEN(aa$) - ii&& + 1, ss)
                xx2$ = MID$(bb$, LEN(bb$) - ii&& + 1, ss)
                IF LEN(xx1$) < LEN(xx2$) THEN SWAP xx1$, xx2$
                aa = VAL(xx1$) + VAL(xx2$) + cc
                IF xx1$ + xx2$ = "" AND cc = 0 THEN EXIT DO ' Prevents leading zeros.
                cc = 0
                IF aa > VAL(STRING$(ss, "9")) THEN aa = aa - 10 ^ ss: cc = 1
                tmp$ = LTRIM$(STR$(aa))
                zz$ = STRING$(LEN(xx1$) - LEN(tmp$), "0") + tmp$ + zz$
            LOOP

            DO WHILE LEFT$(zz$, 1) = "0"
                IF LEFT$(zz$, 1) = "0" THEN zz$ = MID$(zz$, 2)
            LOOP
            IF zz$ = "" THEN zz$ = "0"

            holdaa$ = zz$
        ELSE
            holdaa$ = z$ + STRING$(jj&& - 1, "0")
        END IF

        z$ = "": zz$ = ""

    LOOP UNTIL h&& >= LEN(b$)

    z$ = holdaa$

    IF decimal% THEN
        DO UNTIL LEN(z$) >= dec_a&& + dec_b&&
            z$ = "0" + z$
        LOOP

        z$ = MID$(z$, 0, LEN(z$) - (dec_a&& + dec_b&& - 1)) + "." + MID$(z$, LEN(z$) - (dec_a&& + dec_b&&) + 1)

        DO UNTIL RIGHT$(z$, 1) <> "0" AND RIGHT$(z$, 1) <> "."
            z$ = MID$(z$, 1, LEN(z$) - 1)
        LOOP
    END IF

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = sign$ + z$

    decimal% = 0: sign$ = ""

    runningtotal$ = z$
    RETURN
END SUB

SUB string_compare (compa$, compb$, gl%)
    DO
        ' Remove trailing zeros after a decimal point.
        IF INSTR(compa$, ".") THEN
            DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                compa$ = MID$(compa$, 1, LEN(compa$) - 1)
            LOOP
        END IF
        IF INSTR(compb$, ".") THEN
            DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                compb$ = MID$(compb$, 1, LEN(compb$) - 1)
            LOOP
        END IF

        IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
        IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

        ' A - and +
        IF LEFT$(compa$, 1) = "-" THEN j% = -1
        IF LEFT$(compb$, 1) = "-" THEN k% = -1
        IF k% = 0 AND j% THEN gl% = -1: EXIT DO
        IF j% = 0 AND k% THEN gl% = 1: EXIT DO

        ' A decimal and non-decimal.
        j% = INSTR(compa$, ".")
        k% = INSTR(compb$, ".")

        IF j% = 0 AND k% THEN
            IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
            EXIT DO
        END IF
        IF k% = 0 AND j% THEN
            IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
            EXIT DO
        END IF

        ' Both decimals.
        IF j% THEN
            IF compa$ > compb$ THEN
                gl% = 1
            ELSEIF compa$ = compb$ THEN gl% = 0
            ELSEIF compa$ < compb$ THEN gl% = -1
            END IF
            EXIT DO
        END IF

        ' Both positive or both negative whole numbers.
        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

SUB square_root (x$, sqrt$)
    oldy$ = "": sqrt$ = "": custom_limit&& = 200

    IF INSTR(x$, ".") THEN
        decx$ = MID$(x$, 1, INSTR(x$, ".") - 1)
        x$ = MID$(x$, 1, INSTR(x$, ".") - 1) + MID$(x$, INSTR(x$, ".") + 1)
        IF LEN(x$) = 1 THEN x$ = x$ + "0"
    ELSE
        decx$ = x$
    END IF

    j&& = LEN(decx$)

    ' VAL() okay, one character eval.
    IF VAL(RIGHT$(LTRIM$(STR$(j&&)), 1)) / 2 = VAL(RIGHT$(LTRIM$(STR$(j&&)), 1)) \ 2 THEN
        i&& = 1 ' Even number length.
    ELSE
        i&& = 0 ' Odd number length.
    END IF

    DO
        sm z$, "-", k$, runningtotal$
        z$ = runningtotal$ + (MID$(x$, i&&, 2))
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ' Remove leading zeros

        oldy$ = ""
        FOR j&& = 1 TO 10
            IF i&& > 1 THEN
                sm sqrt$, "*", "2", y$
                y$ = y$ + LTRIM$(STR$(j&&))
            ELSE
                y$ = LTRIM$(STR$(j&&))
            END IF

            sm y$, "*", LTRIM$(STR$(j&&)), runningtotal$

            string_compare runningtotal$, z$, gl%
            IF gl% > -1 THEN
                IF gl% = 0 THEN
                    h% = 0: oldy$ = y$ ' Perfect square division.
                ELSE
                    h% = 1
                END IF
                sm oldy$, "*", LTRIM$(STR$(j&& - h%)), runningtotal$

                IF STRING$(LEN(z$), "0") = z$ AND runningtotal$ = "0" AND i&& >= LEN(decx$) THEN EXIT DO

                IF dpx&& = 0 THEN ' Limited to && size unless converted to string.
                    IF i&& >= LEN(decx$) THEN
                        dpx&& = INT(LEN(decx$) / 2 + .5)
                        IF dpx&& = 0 THEN dpx&& = -1
                    END IF
                END IF

                IF betatest% < -1 THEN PRINT "Sqrt "; sqrt$; " * 2 = ";: COLOR 2, 0: PRINT LTRIM$(STR$(VAL(sqrt$) * 2));: COLOR 7, 0: PRINT LTRIM$(STR$(j&& - h%)); " * "; LTRIM$(STR$(j&& - h%)); " ="; VAL(oldy$) * (j&& - h%)
                sqrt$ = sqrt$ + LTRIM$(STR$(j&& - h%))

                sm oldy$, "*", LTRIM$(STR$(j&& - h%)), runningtotal$
                k$ = runningtotal$

                IF betatest% < -1 THEN PRINT "Remainder "; z$; " minus "; k$; " = ";
                EXIT FOR
            END IF
            oldy$ = y$
        NEXT

        i&& = i&& + 2
        IF LEN(z$) >= custom_limit&& THEN EXIT DO
        x$ = x$ + "00"
    LOOP

    IF dpx&& THEN
        sqrt$ = MID$(sqrt$, 0, dpx&& + 1) + "." + MID$(sqrt$, dpx&& + 1)
    END IF
END SUB

Pete
Reply




Users browsing this thread: 1 Guest(s)