Posts: 730
Threads: 120
Joined: Apr 2022
Reputation:
106
08-03-2022, 10:37 AM
(This post was last modified: 08-03-2022, 12:17 PM by Dav.)
Hey @Stuart, the extra spaces happens to me too. You can edit them out by clicking on the 'View Source' icon just above the editing window on the top left next to the Maximize icon (go into 'Full edit' mode first, not the 'Quick Edit' one). You can also press Ctrl+Shift+S to enter it. After selecting that you can do some 'true' editing. I have to use it all the time to remove those extra spaces in my edited posts.
- Dav
Posts: 2,186
Threads: 222
Joined: Apr 2022
Reputation:
104
@Stuart
Great post! Woohoo, my routine was able to identify .000000000000001184237892933500309785207112630208333333 as an eventual infinite repetend of 3s.
.000000000000001184237892933500309785207112630208333333
So for fun, let's turn that decimal into a fraction...
10^48 * .000000000000001184237892933500309785207112630208333333 = 1184237892933500309785207112630208.333333
10^ 50 * .000000000000001184237892933500309785207112630208333333 = 118423789293350030978520711263020833.3333
118423789293350030978520711263020833.333333
- 1184237892933500309785207112630208.333333
------------------------------------------------------------
117239551400416530668735504150390625
99000000000000000000000000000000000000000000000000 / 117239551400416530668735504150390625 =
1 / 844424930131968
I bring this up because since I'm not onboard with resorting to bit turning math, or whatever it's called, I'm getting curious about converting to fractions to round repetends. As such...
1 / 3 * 3
digital = 1 / 3 = .3... but * 3 = .999... unless the repetend is handled properly in multiplying back to 1.
So with fractions,
1 3
- * - = 1 No problem.
3 1
so if I write an algorithm that does the following...
.3... * 3
10x * .3... = 3.3...
1000x * .3 = 333.3
333.3
- 3.3 = 330
1000x
- 10x = 990x
990x = 330
330 / 990 reduced = 1 /3
1 / 3 * 3 = 3 /3 = 1
So converting to fraction multiplication now 1 / 3 * 3 = 1 instead of .9...
Well, easy in theory, but when we get into really big number repetends, it might be difficult and slow to implement.
Pete
Posts: 2,186
Threads: 222
Joined: Apr 2022
Reputation:
104
Here's a nice little routine I coded using the Euclidean algorithm to determine the GCF and then reducing the fraction. The example uses that big eventual repeating decimal in the last post: .000000000000001184237892933500309785207112630208333333... While the numerator in this example reduces to 1 and only requires 1 loop to calculate, you can remove the REM statements to test something a bit more complicated that takes 4 loops to calculate.
Code: (Select All) WIDTH 166, 25
_SCREENMOVE 0, 0
a$ = "117239551400416530668735504150390625"
b$ = "99000000000000000000000000000000000000000000000000"
REM a$ = "156"
REM b$ = "388"
gfca$ = a$: gfcb$ = b$
IF VAL(gfca$) < VAL(gfcb$) THEN SWAP gfca$, gfcb$
DO
i = i + 1
x = VAL(gfca$) MOD VAL(gfcb$)
SWAP gfca$, gfcb$: gfcb$ = LTRIM$(STR$(x))
IF x = 0 THEN EXIT DO
LOOP
PRINT "Loops:"; i; " ";
PRINT a$; "/"; b$; " ";
PRINT "GFC = "; gfca$; " ";
PRINT LTRIM$(STR$(VAL(a$) / VAL(gfca$))) + "/" + LTRIM$(STR$(VAL(b$) / VAL(gfca$)))
Shoot first and shoot people who ask questions, later.
Posts: 2,186
Threads: 222
Joined: Apr 2022
Reputation:
104
08-03-2022, 10:43 PM
(This post was last modified: 08-03-2022, 11:16 PM by Pete.)
So next up is a way to convert decimals to fractions. This is a test but if it works in all cases, it would be easy to set it up as a conversion calculator. Of course for now, I've left out the string math, so it is limited to around a dozen digits before VAL() craps out. That won't be a problem once it is plugged into the string math routine, later...
Code: (Select All) repetend_class$ = "mixed"
n$ = ".076923076923" ' 1/13th.
IF repetend_class$ = "single" THEN
' Infinite repeating of one digit...
' Loop until the first digit after the decimal is non-zero: i%
i% = 0
DO
i% = i% + 1
x$ = MID$(n$, 1 + i%, 1)
IF VAL(x$) THEN EXIT DO
IF i% = LEN(n$) THEN BEEP: EXIT DO ' Error all zeros.
LOOP
a$ = LTRIM$(STR$(INT(VAL(n$) * 10 ^ (i% + 1)) - INT(VAL(n$) * 10 ^ i%)))
b$ = LTRIM$(STR$(10 ^ (i% + 1) - 10 ^ i%))
ELSE
' Infinite repeating of two or more digits...
i% = 0
DO
i% = i% + 1
x$ = MID$(n$, 1 + i%, 1)
IF VAL(x$) THEN EXIT DO
IF i% = LEN(n$) THEN BEEP: EXIT DO ' Error all zeros.
LOOP
a$ = LTRIM$(STR$(VAL(MID$(n$ + MID$(n$, 2), 2, LEN(n$) - 1 + i%)) - VAL(MID$(n$, 2, i%))))
b$ = LTRIM$(STR$(10 ^ (LEN(n$) - 1 + i%) - 10 ^ i%))
END IF
' GFC algorithm. -------------------------------------------------------------
gfca$ = a$: gfcb$ = b$
IF VAL(gfca$) < VAL(gfcb$) THEN SWAP gfca$, gfcb$
DO
i = i + 1
x = VAL(gfca$) MOD VAL(gfcb$)
SWAP gfca$, gfcb$: gfcb$ = LTRIM$(STR$(x))
IF x = 0 THEN EXIT DO
LOOP
PRINT "Decimal: "; n$
PRINT "Loops:"; i; " "
PRINT "Conversion: "; a$; " / "; b$; " "
PRINT "GFC = "; gfca$; " "
PRINT "Fraction: "; LTRIM$(STR$(VAL(a$) / VAL(gfca$))) + "/" + LTRIM$(STR$(VAL(b$) / VAL(gfca$)))
END
Shoot first and shoot people who ask questions, later.
Posts: 23
Threads: 0
Joined: May 2022
Reputation:
3
(08-03-2022, 10:37 AM)Dav Wrote: Hey @Stuart, the extra spaces happens to me too. You can edit them out by clicking on the 'View Source' icon just above the editing window on the top left next to the Maximize icon (go into 'Full edit' mode first, not the 'Quick Edit' one). You can also press Ctrl+Shift+S to enter it. After selecting that you can do some 'true' editing. I have to use it all the time to remove those extra spaces in my edited posts.
- Dav
Thank you very much for the info about posting and editing; my original post looks so much better now.
Posts: 2,186
Threads: 222
Joined: Apr 2022
Reputation:
104
Okay, this is how we do decimals to fractions in string math...
Code: (Select All) 'repetend_class$ = "mixed"
'n$ = ".076923076923" ' 1/13th.
'repetend_class$ = "single"
'n$ = ".1111" ' 1/9th.
repetend_class$ = "mixed"
n$ = ".052631578947368421" ' 1/19th.
IF repetend_class$ = "single" THEN
' Infinite repeating of one digit...
' Loop until the first digit after the decimal is non-zero: i%
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
a$ = LTRIM$(STR$(INT(VAL(n$) * 10 ^ (ii% + 1)) - INT(VAL(n$) * 10 ^ ii%)))
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$
ELSE
' 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 IF
' GFC algorithm. -------------------------------------------------------------
gfca$ = a$: gfcb$ = b$
IF VAL(gfca$) < VAL(gfcb$) THEN SWAP gfca$, gfcb$
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$
END
a$ = "117239551400416530668735504150390625"
b$ = "99000000000000000000000000000000000000000000000000"
REM a$ = "156"
REM b$ = "388"
a$ = "1428570"
b$ = "9999990"
a$ = "11109"
b$ = "90000"
PRINT i%,
PRINT 10 ^ i%,
PRINT 10 ^ (i% + 1)
PRINT INT(VAL(n$) * 10 ^ (i% + 1)),
PRINT INT(VAL(n$) * 10 ^ i%),
PRINT INT(VAL(n$) * 10 ^ (i% + 1)) - INT(VAL(n$) * 10 ^ i%),
PRINT 10 ^ (i% + 1) - 10 ^ i%
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
So now it can handle very long periodic decimals and convert them. I just need to double check on using VAL() for swapping. I may need to replace that with a string routine, too.
Pete
Posts: 422
Threads: 27
Joined: Apr 2022
Reputation:
26
08-04-2022, 09:23 AM
(This post was last modified: 08-04-2022, 09:28 AM by Jack.)
Pete
for single character it may be faster to do Asc(n$)-48 rather than using Val
also, if you use Val in conjunction with Mid$ to get the value of a character then you can forgo the Mid$ function and use Asc(n$, index)-48
Posts: 23
Threads: 0
Joined: May 2022
Reputation:
3
(08-03-2022, 05:39 PM)Pete Wrote: @Stuart
Great post! Woohoo, my routine was able to identify .000000000000001184237892933500309785207112630208333333 as an eventual infinite repetend of 3s.
.000000000000001184237892933500309785207112630208333333
So for fun, let's turn that decimal into a fraction...
To be honest, at first I started getting a little lost at this point... but I eventually got it.
I'm glad you found the info interesting and useful.
Quote:So next up is a way to convert decimals to fractions. This is a test but if it works in all cases, it would be easy to set it up as a conversion calculator. Of course for now, I've left out the string math, so it is limited to around a dozen digits before VAL() craps out. That won't be a problem once it is plugged into the string math routine, later...
This works unless there are "unique digits" before the repetend begins.
Here's some info I found about converting repeating decimals to fractions even when there are "unique digits" :
https://www.basic-mathematics.com/conver...tions.html
(See Example #2)
Posts: 3,988
Threads: 179
Joined: Apr 2022
Reputation:
222
Function convert2Fraction$ (decimal$)
Function convertRnotation2Fraction$ (rNotedDecimal$)
Function gcd&& (a&&, b&&)
All outlined for integers in post #2, just use String math routines for extended precision..
b = b + ...
Posts: 2,186
Threads: 222
Joined: Apr 2022
Reputation:
104
08-04-2022, 06:30 PM
(This post was last modified: 08-04-2022, 06:31 PM by Pete.)
Fraction to decimal for terminating and non-terminating decimals. For this demo, you'll have to input a repeating mixed decimal like: .142857 would have to be input as: .142857142857. Single repeating like .33333 can be input with at least two digits like: .33
@Stuart Yes, I checked and although the other app I wrote recognizes your leading unique digits repetend, the decimal to fraction does not convert it properly. So the next update I will tweak the routine and hopefully be able to include unique digits in the conversion routine.
For now...
Code: (Select All) LINE INPUT "Decimal: "; n$
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% = 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
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 VAL(gfca$) < VAL(gfcb$) THEN SWAP gfca$, gfcb$
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$
END
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$: PRINT
i = 0: j = 0: k = 0: mp% = 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
@Jack Thanks for the alternative ASC() suggestion. 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. Thanks!
As for VAL(), I intend to update this little project and weed VAL out as much as possible unless VAL() or ASC() will only have limited digits within the bounds of the default datatype for those statements.
Pete
|