Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Don't make me REPETEND myself...
#21
@Stuart Okay, worked out the unique digits before infinite repeating. Just press Enter at prompt, instead of entering a decimal, to see that demo.

Code: (Select All)
WIDTH 165, 25
_SCREENMOVE 0, 0
LINE INPUT "Decimal: "; n$
IF n$ = "" THEN n$ = ".000000000000001184237892933500309785207112630208333333"

GOSUB get_repetend_class

SELECT CASE repetend_class$
    CASE "null" ' Terminating decimals.
        runningtotal$ = "1"
        FOR j = 1 TO LEN(n$)
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        m2$ = runningtotal$

        stringmatha$ = runningtotal$
        stringmathb$ = n$
        operator$ = "*": GOSUB string_multiply
        m1$ = runningtotal$
        a$ = m1$: b$ = m2$

    CASE "single"
        ' Infinite repeating of one digit...
        ' Loop until the first digit after the decimal is non-zero: i%
        ii% = mp% - 1

        runningtotal$ = "1"
        FOR j = 1 TO ii% + 1
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        stringmatha$ = runningtotal$
        stringmathb$ = n$
        operator$ = "*": GOSUB string_multiply
        m1$ = MID$(runningtotal$, 1, INSTR(runningtotal$, ".") - 1)

        runningtotal$ = "1"
        FOR j = 1 TO ii%
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        stringmatha$ = runningtotal$
        stringmathb$ = n$
        operator$ = "*": GOSUB string_multiply
        m2$ = MID$(runningtotal$, 1, INSTR(runningtotal$, ".") - 1)
        stringmatha$ = m1$: stringmathb$ = m2$
        operator$ = "-": GOSUB string_add_subtract
        a$ = runningtotal$

        runningtotal$ = "1"
        FOR j = 1 TO ii%
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        stringmatha$ = m1$: stringmathb$ = runningtotal$

        runningtotal$ = "1"
        FOR j = 1 TO ii% + 1
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        m1$ = runningtotal$
        runningtotal$ = "1"
        FOR j = 1 TO ii%
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        stringmatha$ = m1$: stringmathb$ = runningtotal$
        operator$ = "-": GOSUB string_add_subtract
        b$ = runningtotal$
    CASE ELSE ' Mixed.
        ' Infinite repeating of two or more digits...
        ii% = 0
        DO
            ii% = ii% + 1
            x$ = MID$(n$, 1 + ii%, 1)
            IF x$ <> "0" THEN EXIT DO
            IF ii% = LEN(n$) THEN BEEP: EXIT DO ' Error all zeros.
        LOOP

        stringmatha$ = MID$(n$ + MID$(n$, 2), 2, LEN(n$) - 1 + ii%)
        stringmathb$ = MID$(n$, 2, ii%)
        operator$ = "-": GOSUB string_add_subtract
        a$ = runningtotal$

        runningtotal$ = "1"
        FOR j = 1 TO LEN(n$) - 1 + ii%
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        m1$ = runningtotal$

        runningtotal$ = "1"
        FOR j = 1 TO ii%
            stringmatha$ = runningtotal$: stringmathb$ = "10"
            operator$ = "*": GOSUB string_multiply
        NEXT
        stringmatha$ = m1$: stringmathb$ = runningtotal$
        operator$ = "-": GOSUB string_add_subtract
        b$ = runningtotal$
END SELECT

' GFC algorithm. -------------------------------------------------------------

gfca$ = a$: gfcb$ = b$

IF LEN(gfca$) < LEN(gfca$) THEN
    SWAP gfca$, gfcb$
ELSEIF LEN(gfca$) = LEN(gfca$) THEN
    FOR i = 1 TO LEN(gfca$)
        IF MID$(gfca$, i, 1) < MID$(gfcb$, i, 1) THEN SWAP gfca$, gfcb$: EXIT FOR
    NEXT
END IF

i = 0
DO
    i = i + 1
    ' MOD operation in string math.
    stringmatha$ = gfca$: stringmathb$ = gfcb$
    operator$ = "/": GOSUB string_divide
    m1$ = runningtotal$
    IF INSTR(m1$, ".") THEN m1$ = MID$(m1$, 1, INSTR(m1$, ".") - 1)
    stringmatha$ = m1$
    stringmathb$ = gfcb$
    operator$ = "*": GOSUB string_multiply
    m2$ = runningtotal$

    stringmatha$ = gfca$: stringmathb$ = m2$
    operator$ = "-": GOSUB string_add_subtract
    SWAP gfca$, gfcb$: gfcb$ = runningtotal$
    IF runningtotal$ = "0" THEN EXIT DO
LOOP

stringmatha$ = a$: stringmathb$ = gfca$
operator$ = "/": GOSUB string_divide
numerator$ = runningtotal$
stringmatha$ = b$: stringmathb$ = gfca$
operator$ = "/": GOSUB string_divide
denominator$ = runningtotal$

PRINT "Decimal: "; n$
PRINT "Loops:"; i; " "
PRINT "Conversion: "; a$; " / "; b$; "  "
PRINT "GFC = "; gfca$; "  "
PRINT "Fraction: "; numerator$ + " / " + denominator$
SLEEP
RUN

get_repetend_class:
x$ = MID$(n$, INSTR(n$, ".") + 1)
i = 1: j = 0: k = 0: repetend_class$ = ""
DO
    j = j + 1: k = k + 1
    z$ = MID$(x$, i, j)
    mp% = INSTR(LEN(z$) + i, x$, z$)
    REM COLOR 14, 0: PRINT z$, "i ="; i; "Len ="; LEN(z$); "Prog ="; i + LEN(z$); "mp% ="; mp%; "case ="; p; x$: COLOR 7, 0: SLEEP
    IF VAL(z$) AND mp% = LEN(z$) + i THEN
        FOR k = 0 TO LEN(MID$(x$, i)) / LEN(z$) - 1
            IF MID$(x$, i + k * LEN(z$), LEN(z$)) <> z$ THEN mp% = -1: EXIT FOR
        NEXT

        IF mp% > 0 THEN
            SELECT CASE LEN(z$)
                CASE 1
                    IF i = 1 THEN
                        msg$ = "Repetend infinite: " + STRING$(3, z$) + "..."
                        repetend$ = STRING$(3, z$)
                        repetend_class$ = "single"
                    ELSE
                        msg$ = "Repetend eventually infinite: " + STRING$(3, z$) + "..."
                        repetend$ = STRING$(3, z$)
                        repetend_class$ = "single"
                    END IF
                CASE ELSE
                    msg$ = "Repetend " + z$ + " " + "length = " + LTRIM$(STR$(LEN(z$)))
                    repetend$ = z$
            END SELECT
            EXIT DO
        END IF
    END IF
    IF LEN(z$) >= LEN(x$) - i + 1 / 2 THEN
        msg$ = "Non-repetend."
        repetend_class$ = "null"
        EXIT DO
    END IF
    IF mp% = 0 THEN j = 0: i = i + 1
LOOP
PRINT msg$; "  Repeats at:"; mp% - 1: PRINT
i = 0: j = 0: k = 0: z$ = "": msg$ = ""
RETURN

' String math routines. ------------------------------------------------------
string_divide:
divremainder& = 0: divremainder$ = "": divplace& = 0 AND divplace2& = 0: quotient$ = "": divcarry& = 0
operationdivision% = -1
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: operationdivision% = 0: RETURN '*'
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: EXIT DO
            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$
        m_product$ = "": GOSUB string_multiply
        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(m_product$) OR LEN(tempcutd$) = LEN(m_product$) AND m_product$ <= tempcutd$ THEN EXIT FOR
    NEXT
    quotient$ = quotient$ + LTRIM$(STR$(div_i%))
    stringmatha$ = LTRIM$(STR$(div_i%)): stringmathb$ = d1divisor$
    m_product$ = "": GOSUB string_multiply
    operator$ = "-"
    stringmatha$ = divremainder$
    stringmathb$ = m_product$
    GOSUB string_add_subtract
    divremainder$ = stringmatha$
    operator$ = "/"
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
operationdivision% = 0
stringmathb$ = quotient$: quotient$ = ""
'''GOSUB limit_round_convert
IF stringmathb$ = "overflow" THEN divsign% = 0: operationdivision% = 0: RETURN '*'
'''GOSUB sm_converter
runningtotal$ = stringmathb$: stringmathb$ = ""
IF divsign% THEN runningtotal$ = "-" + runningtotal$

IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
operationdivision% = 0 '''''
RETURN '*'

string_multiply:
m_decimal_places& = 0: m_product$ = "" ''''''''''''''''''''''
fac1$ = stringmatha$: fac2$ = stringmathb$ ' Make numbers whole numbers and remove any - sign.
IF LEFT$(fac1$, 1) = "-" THEN fac1$ = MID$(fac1$, 2): m_sign% = -1
IF LEFT$(fac2$, 1) = "-" THEN fac2$ = MID$(fac2$, 2): IF m_sign% THEN m_sign% = 0 ELSE m_sign% = -1
IF INSTR(fac1$, ".") <> 0 THEN m_decimal_places& = LEN(fac1$) - INSTR(fac1$, "."): fac1$ = MID$(fac1$, 1, INSTR(fac1$, ".") - 1) + MID$(fac1$, INSTR(fac1$, ".") + 1)
IF INSTR(fac2$, ".") <> 0 THEN m_decimal_places& = m_decimal_places& + LEN(fac2$) - INSTR(fac2$, "."): fac2$ = MID$(fac2$, 1, INSTR(fac2$, ".") - 1) + MID$(fac2$, INSTR(fac2$, ".") + 1)
FOR m_i& = LEN(fac2$) TO 1 STEP -1 ' Multiply each charter top and bottom.
    m_k& = m_l&
    m_x2$ = MID$(fac2$, m_i&, 1)
    FOR m_j& = LEN(fac1$) TO 1 STEP -1
        m_x1$ = MID$(fac1$, m_j&, 1)
        IF m_product$ <> "" THEN
            m_add$ = LTRIM$(STR$(VAL(m_x1$) * VAL(m_x2$))) + STRING$(m_k&, "0")
            m_t& = 0: m_xproduct$ = "": m_carry% = 0
            DO ' Add multiplied characters together.
                m_x3$ = MID$(m_add$, LEN(m_add$) - m_t&, 1)
                m_x4$ = MID$(m_product$, LEN(m_product$) - m_t&, 1)
                IF m_x3$ = "" AND m_x4$ = "" THEN
                    IF m_carry% THEN m_xproduct$ = "1" + m_xproduct$
                    EXIT DO
                END IF
                m_g% = VAL(m_x3$) + VAL(m_x4$) + m_carry%
                IF m_g% >= 10 THEN m_g% = m_g% - 10: m_carry% = 1 ELSE m_carry% = 0
                m_xproduct$ = LTRIM$(STR$(m_g%)) + m_xproduct$
                m_t& = m_t& + 1
            LOOP
            m_product$ = m_xproduct$: m_xproduct$ = ""
        ELSE
            m_product$ = LTRIM$(STR$(VAL(m_x1$) * VAL(m_x2$))) + STRING$(m_k&, "0") ' First loop makes variable here.
        END IF
        m_k& = m_k& + 1 ' Adds trailing zeros multiplication
    NEXT
    m_l& = m_l& + 1 ' Used to reset value for m_k& adding one trailing zer for each loop.
NEXT
fac1$ = "": fac2$ = "": m_l& = 0: m_k& = 0: m_t& = 0
IF m_decimal_places& > LEN(m_product$) THEN m_product$ = STRING$(m_decimal_places& - LEN(m_product$), "0") + m_product$ ' Add any leading zeros to a decimal. Ex: .02 * .01 is factored as 002. It needs one leading zero before adding the decimal point, .0002.
IF m_decimal_places& AND m_product$ <> "0" THEN ' Replace any decimal point.
    m_product$ = MID$(m_product$, 1, LEN(m_product$) - m_decimal_places&) + "." + MID$(m_product$, LEN(m_product$) - m_decimal_places& + 1)
END IF
DO UNTIL LEFT$(m_product$, 1) <> "0" ' Remove leading zeros.
    m_product$ = MID$(m_product$, 2)
LOOP
IF m_decimal_places& THEN
    DO UNTIL RIGHT$(m_product$, 1) <> "0" ' Remove trailing zeros in a decimal sum.
        m_product$ = MID$(m_product$, 1, LEN(m_product$) - 1)
    LOOP
END IF
IF m_product$ = "" THEN m_product$ = "0": m_sign% = 0
IF RIGHT$(m_product$, 1) = "." THEN m_product$ = MID$(m_product$, 1, LEN(m_product$) - 1) ' Remove decimal from the end of an integer total.
IF operationdivision% THEN m_sign% = 0: RETURN
stringmathb$ = m_product$: m_product$ = ""
'''GOSUB limit_round_convert
IF stringmathb$ = "overflow" THEN RETURN '*'
'''GOSUB sm_converter
runningtotal$ = stringmathb$: stringmathb$ = ""
IF m_sign% THEN runningtotal$ = "-" + runningtotal$: m_sign% = 0
RETURN

string_add_subtract:
IF INSTR(stringmatha$, ".") <> 0 THEN ' Evaluate sum for decimal fraction.
    sumplace& = LEN(stringmatha$) - INSTR(stringmatha$, ".")
    stringmatha$ = MID$(stringmatha$, 1, INSTR(stringmatha$, ".") - 1) + MID$(stringmatha$, INSTR(stringmatha$, ".") + 1) ' Strip out decimal
END IF
IF INSTR(stringmathb$, ".") <> 0 THEN ' Evaluate number for decimal fraction.
    numplace& = LEN(stringmathb$) - INSTR(stringmathb$, ".")
    stringmathb$ = MID$(stringmathb$, 1, INSTR(stringmathb$, ".") - 1) + MID$(stringmathb$, INSTR(stringmathb$, ".") + 1) ' Strip out decimal
END IF
IF sumplace& > numplace& THEN addsubplace& = sumplace& ELSE addsubplace& = numplace&
IF sumplace& > addsubplace& THEN
    stringmatha$ = stringmatha$ + STRING$(sumplace& - addsubplace&, "0")
ELSEIF addsubplace& > sumplace& THEN
    stringmatha$ = stringmatha$ + STRING$(addsubplace& - sumplace&, "0")
END IF
IF numplace& > addsubplace& THEN
    stringmathb$ = stringmathb$ + STRING$(numplace& - addsubplace&, "0")
ELSEIF addsubplace& > numplace& THEN
    stringmathb$ = stringmathb$ + STRING$(addsubplace& - numplace&, "0")
END IF ' END Decimal evaluations.

IF LEFT$(stringmatha$, 1) = "-" THEN sign_input$ = "-" ELSE sign_input$ = "+"
IF LEFT$(stringmathb$, 1) = "-" THEN sign_total$ = "-" ELSE sign_total$ = "+"

addsubsign% = 0
SELECT CASE sign_input$ + operator$ + sign_total$
    CASE "+++", "+--"
        operator$ = "+"
        IF LEFT$(stringmathb$, 1) = "-" THEN stringmathb$ = MID$(stringmathb$, 2)
    CASE "++-", "+-+"
        operator$ = "-"
        IF LEFT$(stringmathb$, 1) = "-" THEN stringmathb$ = MID$(stringmathb$, 2)
        IF VAL(stringmathb$) > VAL(stringmatha$) THEN SWAP stringmatha$, stringmathb$: addsubsign% = -1
    CASE "---", "-++"
        operator$ = "-"
        IF LEFT$(stringmatha$, 1) = "-" THEN stringmatha$ = MID$(stringmatha$, 2)
        IF LEFT$(stringmathb$, 1) = "-" THEN stringmathb$ = MID$(stringmathb$, 2)
        IF VAL(stringmathb$) > VAL(stringmatha$) THEN SWAP stringmatha$, stringmathb$ ELSE addsubsign% = -1
    CASE "--+", "-+-"
        operator$ = "+"
        IF LEFT$(stringmatha$, 1) = "-" THEN stringmatha$ = MID$(stringmatha$, 2)
        IF LEFT$(stringmathb$, 1) = "-" THEN stringmathb$ = MID$(stringmathb$, 2)
        addsubsign% = -1
END SELECT

IF LEN(stringmatha$) > LEN(stringmathb$) THEN
    stringmathb$ = STRING$(LEN(stringmatha$) - LEN(stringmathb$), "0") + stringmathb$
ELSEIF LEN(stringmatha$) < LEN(stringmathb$) THEN
    stringmatha$ = STRING$(LEN(stringmathb$) - LEN(stringmatha$), "0") + stringmatha$
END IF
addsubx1$ = ""

SELECT CASE operator$
    CASE "+", "="
        FOR addsubii& = LEN(stringmatha$) TO 1 STEP -1
            addsubx1% = VAL(MID$(stringmatha$, addsubii&, 1)) + VAL(MID$(stringmathb$, addsubii&, 1)) + addsubcarry%
            IF addsubx1% > 9 THEN addsubx1% = addsubx1% - 10: addsubcarry% = 1 ELSE addsubcarry% = 0
            addsubx1$ = LTRIM$(STR$(addsubx1%)) + addsubx1$
        NEXT
        IF addsubcarry% THEN addsubx1$ = "1" + addsubx1$: addsubcarry% = 0
        GOSUB replace_decimal
    CASE "-"
        FOR addsubii& = LEN(stringmatha$) TO 1 STEP -1
            addsubx1% = VAL(MID$(stringmatha$, addsubii&, 1)) - VAL(MID$(stringmathb$, addsubii&, 1)) + addsubcarry%
            IF addsubx1% < 0 THEN addsubx1% = addsubx1% + 10: addsubcarry% = -1 ELSE addsubcarry% = 0
            addsubx1$ = LTRIM$(STR$(addsubx1%)) + addsubx1$
        NEXT
        IF addsubx1$ <> "" AND addsubx1$ <> STRING$(LEN(addsubx1$), "0") THEN GOSUB replace_decimal
        DO UNTIL LEFT$(addsubx1$, 1) <> "0" ' Remove leading zeros.
            addsubx1$ = MID$(addsubx1$, 2)
        LOOP
        IF addsubx1$ = "" THEN
            addsubx1$ = "0": addsubsign% = 0
        ELSE
            IF addsubcarry% THEN addsubx1$ = "-" + addsubx1$: addsubcarry% = 0
        END IF
END SELECT

IF addsubsign% THEN
    IF LEFT$(addsubx1$, 1) = "-" THEN addsubx1$ = MID$(addsubx1$, 2) ELSE addsubx1$ = "-" + addsubx1$
END IF
stringmatha$ = addsubx1$: addsubx1$ = ""
IF operationdivision% THEN RETURN
stringmathb$ = stringmatha$: stringmatha$ = ""
IF LEFT$(stringmathb$, 1) = "-" THEN
    stringmathb$ = MID$(stringmathb$, 2)
    n2sign$ = "-"
ELSE
    n2sign$ = ""
END IF
''' GOSUB limit_round_convert
IF stringmathb$ = "overflow" THEN n2sign$ = "": RETURN '*'
''' GOSUB sm_converter
runningtotal$ = n2sign$ + stringmathb$: n2sign$ = ""
RETURN

replace_decimal:
IF addsubplace& THEN
    addsubx1$ = STRING$(addsubplace& - LEN(addsubx1$), "0") + addsubx1$
    addsubx1$ = MID$(addsubx1$, 1, LEN(addsubx1$) - addsubplace&) + "." + MID$(addsubx1$, LEN(addsubx1$) - addsubplace& + 1)
    DO UNTIL RIGHT$(addsubx1$, 1) <> "0" ' Remove trailing zeros in a decimal sum.
        addsubx1$ = MID$(addsubx1$, 1, LEN(addsubx1$) - 1)
        addsubplace& = addsubplace& - 1
    LOOP
    IF RIGHT$(addsubx1$, 1) = "." THEN addsubx1$ = MID$(addsubx1$, 1, LEN(addsubx1$) - 1) ' Number is now an integer.
END IF
RETURN


Pete
Reply
#22
Pete said " I've used this statement for years for a variety of things but was not aware of the optional indexing. Always nice to learn something along the way"
you can also use the Asc statement like this
a$="123"
Asc(a$, 1) = 48
Print a$ '--> 023
not sure that Asc was designed to function that way however, it could be a "feature"
just for fun I replaced Val with Asc where possible in the Treebeard's string-math and the multiply was 14 times faster, division was 40% faster
Reply
#23
(08-04-2022, 10:37 PM)Jack Wrote: Pete said " I've used this statement for years for a variety of things but was not aware of the optional indexing. Always nice to learn something along the way"
you can also use the Asc statement like this
a$="123"
Asc(a$, 1) = 48
Print a$ '--> 023
not sure that Asc was designed to function that way however, it could be a "feature"
just for fun I replaced Val with Asc where possible in the Treebeard's string-math and the multiply was 14 times faster, division was 40% faster

Huh? I must be going in the WRONG direction, because I just figured out a way to make mine 14 times slower!

How to handle really big numbers using STRING VAL()

Code: (Select All)
CLS
WIDTH 160, 25
_SCREENMOVE 0, 0
neg_a = 0: neg_b = 0: dec_a1$ = "": dec_a2$ = "": dec_b1$ = "": dec_b2$ = ""

LINE INPUT "First number  a:  "; a$
LINE INPUT "Second number b: "; b$

IF b$ = "" THEN ' Demo if nothing input.
    a$ = "11" + STRING$(50000, "0") + "1.001"
    b$ = "11" + STRING$(50000, "0") + "1.002"
END IF

REM Remove trailing zeros after a decimal point.
IF INSTR(a$, ".") THEN
    DO UNTIL RIGHT$(a$, 1) <> "0" AND RIGHT$(a$, 1) <> "." AND RIGHT$(a$, 1) <> "-"
        a$ = MID$(a$, 1, LEN(a$) - 1)
    LOOP
END IF
IF INSTR(b$, ".") THEN
    DO UNTIL RIGHT$(b$, 1) <> "0" AND RIGHT$(b$, 1) <> "." AND RIGHT$(b$, 1) <> "-"
        b$ = MID$(b$, 1, LEN(b$) - 1)
    LOOP
END IF

IF MID$(a$, 1, 2) = "-0" OR a$ = "" OR a$ = "-" THEN a$ = "0"
IF MID$(b$, 1, 2) = "-0" OR b$ = "" OR b$ = "-" THEN b$ = "0"


IF MID$(a$, 1, 1) = "-" THEN neg_a = -1
IF MID$(b$, 1, 1) = "-" THEN neg_b = -1
IF INSTR(a$, ".") THEN
    dec_a1$ = MID$(a$, 1, INSTR(a$, ".") - 1): dec_a2$ = MID$(a$, INSTR(a$, ".") + 1)
ELSE
    dec_a1$ = a$
END IF

IF INSTR(b$, ".") THEN
    dec_b1$ = MID$(b$, 1, INSTR(b$, ".") - 1): dec_b2$ = MID$(b$, INSTR(b$, ".") + 1)
ELSE
    dec_b1$ = b$
END IF

DO
    ' Test for sign.
    SELECT CASE neg_a + neg_b
        CASE 0, -2 ' Both positive or negative
            IF dec_a1$ = dec_b1$ AND dec_a2$ = dec_b2$ THEN a_less_b = 0: EXIT DO ' Same number.
            IF LEN(dec_a1$) AND dec_b1$ = "" THEN a_less_b = 1: EXIT DO ' a >=1 and b is a decimal.
            IF LEN(dec_b1$) AND dec_a1$ = "" THEN a_less_b = -1: EXIT DO ' b >=1 and a is a decimal.
            IF LEN(dec_a1$) AND dec_a1$ <> dec_b1$ OR LEN(dec_b1$) AND dec_a1$ <> dec_b1$ THEN ' One or both >=1 and non-decimal parts are not equal.
                IF LEN(dec_a1$) > LEN(dec_b1$) THEN a_less_b = 1: EXIT DO
                IF LEN(dec_a1$) < LEN(dec_b1$) THEN a_less_b = -1: EXIT DO
                IF LEN(dec_a1$) = LEN(dec_b1$) THEN
                    FOR i = 1 TO LEN(dec_a1$)
                        IF MID$(dec_a1$, i, 1) <> MID$(dec_b1$, i, 1) THEN EXIT FOR
                    NEXT
                    IF MID$(dec_a1$, i, 1) < MID$(dec_b1$, i, 1) THEN a_less_b = -1: EXIT DO ELSE a_less_b = 1: EXIT DO
                END IF
            ELSE ' Both decimals or non-decimal digits are the same and cancel out.
                j = LEN(dec_a2$)
                IF LEN(dec_b2$) > j THEN j = LEN(dec_b2$)
                FOR i = i TO j
                    IF MID$(dec_a2$, i, 1) <> MID$(dec_b2$, i, 1) THEN EXIT FOR
                NEXT
                IF MID$(dec_a2$, i, 1) < MID$(dec_b2$, i, 1) THEN a_less_b = -1: EXIT DO ELSE a_less_b = 1: EXIT DO
            END IF
        CASE -1 ' One is negative.
            j = -999
            IF neg_a THEN a_less_b = -1: EXIT DO ELSE a_less_b = 1: EXIT DO
    END SELECT
    EXIT DO
LOOP
IF neg_a OR neg_b THEN IF j <> -999 THEN a_less_b = a_less_b * -1
PRINT: IF LEN(a$) < 60 AND LEN(b$) < 60 THEN PRINT a$; "  "; b$, ELSE PRINT "Number(s) too big to print to line.",
IF a_less_b < 0 THEN PRINT "a$ < b$" ELSE IF a_less_b = 0 THEN PRINT "a$ = b$" ELSE PRINT "b$ < a$"
REM PRINT dec_a1$, dec_a2$, dec_b1$, dec_b2$, neg_a, neg_b
PRINT
SLEEP
RUN


For super large numbers these two comparison standards are unreliable...

' String comparison fails.
PRINT "a$ < b$ "; a$ < b$
PRINT "a$ = b$ "; a$ = b$
PRINT "a$ > b$ "; a$ > b$
PRINT
' Value comparison fails.
PRINT "VAL(a$) < VAL(b$) "; VAL(a$) < VAL(b$)
PRINT "VAL(a$) = VAL(b$) "; VAL(a$) = VAL(b$)
PRINT "VAL(a$) > VAL(b$) "; VAL(a$) > VAL(b$)
PRINT

Pete
Reply
#24
A simpler way of doing the string comparison in the last post...

Code: (Select All)
betatest% = -1
DO
    DO
        LINE INPUT "a$ = "; a$
        LINE INPUT "b$ = "; b$

        REM Remove trailing zeros after a decimal point.
        IF INSTR(a$, ".") THEN
            DO UNTIL RIGHT$(a$, 1) <> "0" AND RIGHT$(a$, 1) <> "." AND RIGHT$(a$, 1) <> "-"
                a$ = MID$(a$, 1, LEN(a$) - 1)
            LOOP
        END IF
        IF INSTR(b$, ".") THEN
            DO UNTIL RIGHT$(b$, 1) <> "0" AND RIGHT$(b$, 1) <> "." AND RIGHT$(b$, 1) <> "-"
                b$ = MID$(b$, 1, LEN(b$) - 1)
            LOOP
        END IF

        IF MID$(a$, 1, 2) = "-0" OR a$ = "" OR a$ = "-" THEN a$ = "0"
        IF MID$(b$, 1, 2) = "-0" OR b$ = "" OR b$ = "-" THEN b$ = "0"

        ' A - and +
        IF LEFT$(a$, 1) = "-" THEN j% = -1
        IF LEFT$(b$, 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(a$, ".")
        k% = INSTR(b$, ".")
        IF j% = 0 AND k% THEN
            IF a$ = "0" THEN gl% = -1 ELSE gl% = 1
            EXIT DO
        END IF
        IF k% = 0 AND j% THEN
            IF b$ = "0" THEN gl% = 1 ELSE gl% = -1
            EXIT DO
        END IF

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

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

    IF betatest% THEN
        PRINT
        SELECT CASE gl%
            CASE -1
                PRINT "a$ < b$", a$; " < "; b$; "  gl% = "; LTRIM$(STR$(gl%))
            CASE 0
                PRINT "a$ = b$", a$; " = "; b$; "  gl% = "; LTRIM$(STR$(gl%))
            CASE 1
                PRINT "a$ > b$", a$; " > "; b$; "  gl% = "; LTRIM$(STR$(gl%))
        END SELECT
        PRINT
    END IF
LOOP
Reply




Users browsing this thread: 5 Guest(s)