RE: Don't make me REPETEND myself... - Pete - 08-04-2022
@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
RE: Don't make me REPETEND myself... - Jack - 08-04-2022
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
RE: Don't make me REPETEND myself... - Pete - 08-05-2022
(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
RE: Don't make me REPETEND myself... - Pete - 08-14-2022
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
|