Don't make me REPETEND myself... - Pete - 07-31-2022
So Jack got me working on string math again. I don't know whether to thank him or shoot him (refers to avatar) but, here we go again...
I was thinking if I ever want to address using repetends (repeating decimals) to make even simple string equations like 1 / 3 * 3 = 1, instead of .999... then I might need to explore how to identify those repeating decimal occurrences.
Below is a sample program (non idiot-proof so don't post it accepted invalid data) that I hope detects all instances of repetends. I coded the first part, and then added (pasted) in the division routine from my string math program.
Try inputting 1 as the numerator and 97 as the denominator and you will largest repetend I know of, 96 digits befor the sequence repeats!
Code: (Select All) WIDTH 170, 42
_SCREENMOVE 0, 0
DO
DIM SHARED runningtotal$, limit&&
limit&& = 200
LINE INPUT "Numerator: "; a$
LINE INPUT "Denominator: "; b$
calcdiv a$, b$
COLOR 14, 0: PRINT runningtotal$; " ";: COLOR 7, 0
IF INSTR(runningtotal$, ".") THEN
x$ = MID$(runningtotal$, INSTR(runningtotal$, ".") + 1)
x$ = MID$(x$, LEN(b$) - LEN(a$) + 2)
FOR i = 1 TO LEN(x$)
k = j
j = INSTR(i + 1, x$, MID$(x$, 1, i))
IF j = k THEN EXIT FOR
NEXT
SELECT CASE j
CASE 0
IF MID$(x$, 1, 2) <> MID$(x$, 2, 2) OR LEN(x$) < 2 THEN
msg$ = "Non-repetend."
ELSE
IF MID$(runningtotal$, INSTR(runningtotal$, ".") + 1, 1) <> MID$(x$, 1, 1) THEN
msg$ = "Eventual infinite repetend."
ELSE
msg$ = "Repetend infinite."
END IF
END IF
CASE ELSE
msg$ = "Repetend length: " + LTRIM$(STR$(j - 1))
END SELECT
ELSE
msg$ = "Non-decimal"
END IF
PRINT msg$
CLEAR
PRINT
LOOP
SUB calcdiv (a$, b$)
stringmatha$ = a$
stringmathb$ = b$
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.": 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: 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: EXIT SUB
'''GOSUB sm_converter
runningtotal$ = stringmathb$: stringmathb$ = ""
IF divsign% THEN runningtotal$ = "-" + runningtotal$
IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
EXIT SUB
string_multiply:
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 EXIT SUB
'''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$ = "": EXIT SUB
''' 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
END SUB
For you math folks, if you have a more elegant way to do this, I'd love to see it. Also, please excuse the message for "Eventual infinite repetend." I used this made up term to describe fractions like 1 / 6 where the digits repeat, but not immediately following the decimal point like 1 / 3 does. If you know the correct term for this type of repetend, please let me know.
Pete
RE: Don't make me REPETEND myself... - bplus - 07-31-2022
I did this years ago, I wonder if I could dig it up. In fact I did this with base 2 numbers! Because drawing the bar codes made some fabulous designs.
Ah I did find it in no time! Search divide and there under math/division is, n divided by d:
Code: (Select All) _Title "n slash d to R notation and back again" '2019-04-24
' from:"Decimal Expansion of Division without Dividing by bplus 2017-12-03"
' dove tailing Adrians and my recent dividing programs
' 2019-04-24
' I want to isolate the repeated section immediately not write the fraction out and then repeat the repeated section
' not 1/6 = .16R6 >>> but .1R6
'hmm... look like have to cycle through twice to get the length of the repeat section
' but before returning backup to start of repeat section insert the R where it starts the first time
' and end it where " repeat " starts.
'2019-04-24
' just for kicks, convert the R notation back to fraction if possible.
' Had to revert back to the redundant " repeat " form of R notation.
'2019-04-27 Thanks to Jack002's comments and replies this code to calculate adj&& may have been improved.
Randomize Timer
DefLng A-Z
Do
Print: Print "Enter 2 integers < 3200, numerator / denominator, 0's quit, don't forget / "
Input nd$
slash = InStr(nd$, "/")
If slash Then
dvsr = Val(Mid$(nd$, slash + 1))
If dvsr = 0 Then Print "Divisor is 0, bye.": End
numerator = Val(Mid$(nd$, 1, slash - 1))
If numerator = 0 Then Print "Numerator is 0, bye.": End
Else
Print "No slash found, bye.": End
End If
Cls
d$ = divide$(numerator, dvsr)
Print numerator; " / "; dvsr; " = "; d$
'and now arttemp"t to convert back to fraction
Print: Print "Check if can convert back to fraction:"
result$ = convertRnotation2Fraction$(d$)
If result$ <> "" Then Print result$
Loop
Function convertRnotation2Fraction$ (rNotedDecimal$)
'check if R in the decimal
dotPos = InStr(rNotedDecimal$, ".")
If dotPos = 0 Then convertRnotation2Fraction$ = rNotedDecimal$: Exit Function
RPos = InStr(rNotedDecimal$, " repeat ")
If RPos = 0 Then convertRnotation2Fraction$ = convert2Fraction$(rNotedDecimal$): Exit Function
'still here? we have an R and a decimal
whole$ = Mid$(rNotedDecimal$, 1, dotPos - 1)
If Val(whole$) = 0 Then whole$ = ""
p = Len(rNotedDecimal$) - RPos - Len(" repeat ") + 1
Print "Debug: repeat length ="; p
If p > 12 Then
Print "The length of the repeat section of: "
Print rNotedDecimal$
Print " is too long to convert back to fraction."
Exit Function
End If
dec$ = Mid$(rNotedDecimal$, dotPos)
Print "Debug: converting dec$ "; dec$
'remove " repeat "
RPos = InStr(dec$, " repeat ")
dec1$ = Mid$(dec$, 1, RPos - 1) + Mid$(dec$, RPos + Len(" repeat "))
dec2$ = Mid$(dec$, 1, RPos - 1)
Print "Debug: dec1$ (double repeat), dec2$ (single repeat) = "; dec1$; ", "; dec2$
'mult by 10^p to get the 2nd repeat part in dec1$ aligned to 1st repeat part in dec2$
vd1## = Val(dec1$) * 10 ^ p
vd2## = Val(dec2$)
n## = vd1## - vd2## 'subtract dec2$ from dec1$
'adj&& = 1 'convert to whole numbers
'WHILE n## <> INT(n##)
' adj&& = adj&& * 10
' n## = n## * 10
'WEND
'calculate adj&& from length of decimal
ns$ = Str$(n##)
dot = InStr(ns$, ".")
p2 = Len(ns$) - dot
adj&& = 10 ^ p2
'reevaluate to avoid rounding errors from crazy floating point math
n1&& = vd1## * adj&& - vd2## * adj&&
Print "Debug values: vd1, vd2, adj&&, n1&& (difference * adj&& for whole number):"
Print vd1##; ", "; vd2##; ", "; adj&&; ", "; n1&&
d&& = (10 ^ p - 1) * adj&&
Print "Debug: Giant numerator, denominator "; n1&&; ", "; d&& 'giant numbers
'reduce giant numbers by Gretaest Common Divisor between them
g&& = gcd&&(n1&&, d&&): sn&& = n1&& / g&&: sd&& = d&& / g&&
convertRnotation2Fraction$ = whole$ + " " + _Trim$(Str$(sn&&)) + "/" + _Trim$(Str$(sd&&))
End Function
Function convert2Fraction$ (decimal$)
dot%% = InStr(decimal$, ".")
If dot%% > 0 Then
whole$ = Mid$(decimal$, 1, dot%% - 1)
If Val(whole$) = 0 Then whole$ = ""
p%% = Len(decimal$) - dot%%
n&& = Val(Mid$(decimal$, dot%% + 1))
d&& = 10 ^ p%%
g&& = gcd&&(n&&, d&&): sn&& = n&& / g&&: sd&& = d&& / g&&
convert2Fraction$ = whole$ + " " + _Trim$(Str$(sn&&)) + "/" + _Trim$(Str$(sd&&))
Else
convert2Fraction$ = decimal$
End If
End Function
Function gcd&& (a&&, b&&)
'a and b will be changed unless make copies
c&& = a&&: d&& = b&&
While c&& <> 0 And d&& <> 0
If c&& > d&& Then c&& = c&& Mod d&& Else d&& = d&& Mod c&&
Wend
gcd&& = c&& + d&&
End Function
Function divide$ (n, d)
'n = original product or numerator (preserve value of n)
'd = divisor (also preserve value)
c = n 'copy of n to be reduced until <= d, c will be the remainder part of division
a = 0 'a is for answer or accumulate, the integer part of the division result
'find lowest power of 10 such that: d * 10^p > n
p = 0 'power of 10
While d * (10 ^ p) < n
p = p + 1
Wend
While c >= d
If c = d Then a = a + 1: c = 0: Exit While
p = p - 1
If p >= 0 Then
m = 0
While d * m * 10 ^ p < c
m = m + 1
Wend
m = m - 1
c = c - d * m * 10 ^ p
a = a + m * 10 ^ p
End If
Wend
'Now for the decimal expansion isolating the repeating part if one
If c <> 0 Then
Dim b(d)
b$ = "."
While c <> 0
'emergency bug out!
loopct = loopct + 1 'loop count should not exceed 1000 for numbers I am testing
If loopct > 1000 Then Print "Error: loop too long, bugging out! ": GoTo skip
'track repeats b() tracks been here once, b2() tracks been here twice
If b(c) = 1 Then 'been here!
If rFlag = 1 Then 'been here twice!
If b2(c) = 1 Then Exit While 'strike 3, we're out of here
b2(c) = 1
Else
rFlag = 1
Dim b2(d)
b$ = b$ + " repeat "
b2(c) = 1
End If
Else
b(c) = 1
End If
'c was last remainder, mult by 10 and see if some m * d > can reduce it
tc = 10 * c
flag = 0
For m = 0 To 9
If ((tc - m * d) >= 0) And ((tc - (m + 1) * d) < 0) Then
flag = 1: b$ = b$ + LTrim$(Str$(m))
Exit For
End If
Next
If flag = 0 Then b$ = b$ + "0": m = 0
c = tc - d * m
Wend
End If
'OK either d divided n eventually or there is a repeated pattern recorded in b$
skip: '< needed for debugging
r$ = Str$(a)
If b$ <> "" Then r$ = r$ + b$
divide$ = r$
End Function
The repeating part is isolated and named and measured.
1/97 you are just getting started 1/269 is 268 long 1/(big prim number) always a good bet to be long.
RE: Don't make me REPETEND myself... - Pete - 08-01-2022
I hope you have it handy.
I just tweaked what I have just a bit. The original works, but I fudged it a bit. Right now, 1 / 6 = .1666 (6s repeat) and 1 / 7 = .142857... So I made the algorithm look past the first digit so it would see .666... and .428571... That would be fine for detecting the pattern further into the decimal, well, fine until you wanted to assign a variable to show the repetend.
So...
Code: (Select All) WIDTH 170, 42
_SCREENMOVE 0, 0
DO
DIM SHARED runningtotal$, limit&&
limit&& = 200
LINE INPUT "Numerator: "; a$
LINE INPUT "Denominator: "; b$
calcdiv a$, b$
COLOR 14, 0: PRINT runningtotal$; " ";: COLOR 7, 0
IF INSTR(runningtotal$, ".") THEN
x$ = MID$(runningtotal$, INSTR(runningtotal$, ".") + 1)
x$ = MID$(x$, LEN(b$) - LEN(a$))
FOR i = 1 TO LEN(x$)
k = j
j = INSTR(i + 1, x$, MID$(x$, 1, i))
IF j = k THEN EXIT FOR
NEXT
SELECT CASE j
CASE 0
IF LEN(x$) >= limit&& AND INSTR(runningtotal$, STRING$(limit&&, MID$(x$, LEN(x$), 1))) THEN
IF x$ <> STRING$(LEN(x$), MID$(x$, 1, 1)) THEN
msg$ = "Eventual infinite repetend."
repetend$ = STRING$(3, MID$(x$, LEN(x$), 1))
ELSE
msg$ = "Repetend infinite."
repetend$ = STRING$(3, MID$(x$, LEN(x$), 1))
END IF
ELSE
j = -1: msg$ = "Non-repetend."
END IF
CASE ELSE
msg$ = "Repetend length = " + LTRIM$(STR$(j - 1))
repetend$ = MID$(x$, 1, j - 1)
END SELECT
ELSE
j = -1: msg$ = "Non-decimal"
END IF
PRINT msg$; " ";
COLOR 3, 0
PRINT repetend$;: IF j = 0 THEN PRINT "..." ELSE PRINT
COLOR 7, 0
CLEAR
PRINT
LOOP
SUB calcdiv (a$, b$)
stringmatha$ = a$
stringmathb$ = b$
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.": 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: 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: EXIT SUB
'''GOSUB sm_converter
runningtotal$ = stringmathb$: stringmathb$ = ""
IF divsign% THEN runningtotal$ = "-" + runningtotal$
IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
EXIT SUB
string_multiply:
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 EXIT SUB
'''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$ = "": EXIT SUB
''' 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
END SUB
Pete
RE: Don't make me REPETEND myself... - bplus - 08-01-2022
Yeah, this is definitely a fruitful exercise to work out on your own with Basic.
RE: Don't make me REPETEND myself... - Pete - 08-01-2022
I've implemented this into the calculator, but without knowing the rules and if my algorithms are the same as those used by precision calculators I feel like I may be wasting my time. For instance...
1 / 3 will be reported as .333... (Actually, the last digit gets rounded down and since that is zero, the trailing zero digit is removed.
1 / 6 will be reported as .16667 (The last digit of 6 is rounded up to 7.)
So I would have to adjust my calculator to display .16667 but keep in memory .1666... for the next calculation.
Weird, but some online calculators will not allow you to divide and multiply back to get to the same number. For instance:
https://calculator-1.com/
1 / 3 = .333... * 3 = .999... instead of 1!
I think the better calculators display rounded but base the next calculation on the un-rounded result, so 1 / 3 = .333... * 3 = 1.
I really wish I could find the accepted math algorithm that allows for several divisions of a number would result in the original number using the same numbers to multiply in reverse order.
1 / 6 / 3 / 7 / 9 * 9 * 7 * 3 * 6 = 1
I'm very close, but still not quite there yet.
Pete
RE: Don't make me REPETEND myself... - Jack - 08-01-2022
hi Pete
the Windows Calculator is open source https://github.com/microsoft/calculator
it seems to be written in C#
Quote:Infinite precision for basic arithmetic operations (addition, subtraction, multiplication, division) so that calculations never lose precision.
I tried to find where in the source the math is performed but failed to find it
RE: Don't make me REPETEND myself... - Pete - 08-03-2022
I tried do view the code for the windows calculator, but my browser wouldn't load it.
So I had a couple of tests that required me to rethink the repetend routine a bit.
Here is where I'm at so far with a few test cases included. It works on all of these. If you can find a repetition that breaks it, let me know.
Also, I'm trying to figure out if I should bother with times where there are not enough digits reported to fully identify a repeating decimal. If so, how many repeating digits would be enough to would be a repetend if more digits were reported?
Code: (Select All) _SCREENMOVE 0, 0
WIDTH 160, 42
DO
p = p + 1
SELECT CASE p
CASE 1: a$ = ".0033125"
CASE 2: a$ = "33125"
CASE 3: a$ = ".331253312533125"
CASE 4: a$ = ".00000331253312533125"
CASE 5: a$ = ".333"
CASE 6: a$ = ".000001666"
CASE 7: a$ = ".00000333"
CASE 8: a$ = "3.141592174932847"
CASE 9: a$ = "6.00000011127501112750111275"
CASE 10: a$ = ".01111411111411114111114"
CASE 11: a$ = ".000881834215167548500881834215167548500881834215167548500881834215167"
CASE ELSE
END
END SELECT
a$ = MID$(a$, INSTR(a$, ".") + 1)
i = 1: j = 0: k = 0
DO
j = j + 1: k = k + 1
z$ = MID$(a$, i, j)
mp% = INSTR(LEN(z$) + i, a$, z$)
REM COLOR 14, 0: PRINT z$, "i ="; i; "Len ="; LEN(z$); "Prog ="; i + LEN(z$); "mp% ="; mp%; "case ="; p; a$: COLOR 7, 0: SLEEP
IF VAL(z$) AND mp% = LEN(z$) + i THEN
FOR k = 0 TO LEN(MID$(a$, i)) / LEN(z$) - 1
IF MID$(a$, 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$) + "..."
ELSE
msg$ = "Repetend eventually infinite: " + STRING$(3, z$) + "..."
END IF
CASE ELSE
msg$ = "Repetend " + z$ + " " + "length = " + LTRIM$(STR$(LEN(z$)))
END SELECT
EXIT DO
END IF
END IF
IF LEN(z$) >= LEN(a$) - i + 1 / 2 THEN msg$ = "Non-repetend.": EXIT DO
IF mp% = 0 THEN j = 0: i = i + 1
LOOP
PRINT msg$, a$: PRINT
LOOP
RE: Don't make me REPETEND myself... - Jack - 08-03-2022
Pete I can't answer that, on the other hand, have heard of posit/unum's ?
Dr. John L. Gustafson http://web.stanford.edu/class/ee380/Abstracts/170201.html came up with a different way to do computer arithmetic
here's a 1 and 1/2 hour video https://youtu.be/aP0Y1uAA-2Y
Wikipedia https://en.wikipedia.org/wiki/Unum_(number_format)
RE: Don't make me REPETEND myself... - Pete - 08-03-2022
(08-03-2022, 01:39 AM)Jack Wrote: Pete I can't answer that, on the other hand, have heard of posit/unum's ?
Dr. John L. Gustafson http://web.stanford.edu/class/ee380/Abstracts/170201.html came up with a different way to do computer arithmetic
here's a 1 and 1/2 hour video https://youtu.be/aP0Y1uAA-2Y
Wikipedia https://en.wikipedia.org/wiki/Unum_(number_format)
Trying my best to avoid anything to do with BCD (binary coded decimal) manipulation. Sure, it looks fun if you want to soak in the whole information pool and redo the program to turn bits rather than string numbers. Of course, the really good online precision calculators may be based on just that.; in which case the best I can do is approximate something between those apps and the ones that ignore repetends all together.
I looked up the largest repetend online. While 1 / 9973 gives a decimal repetend of 554 digits, the supposed largest is 1 / 9967, which gives a whopping 9966 decimal digits before repeating! I had to set my string math limit&& variable to 20,000 places to test it.
Working with 20,000 digits for each division calculation to catch something like this would make my calculator way too slow; about 2 to 3-seconds per non-terminating calculations.
RE: Don't make me REPETEND myself... - Stuart - 08-03-2022
(07-31-2022, 08:57 PM)Pete Wrote: For you math folks, if you have a more elegant way to do this, I'd love to see it. Also, please excuse the message for "Eventual infinite repetend." I used this made up term to describe fractions like 1 / 6 where the digits repeat, but not immediately following the decimal point like 1 / 3 does. If you know the correct term for this type of repetend, please let me know.
Pete
There is no official name for the digits that precede the repetend.
I have seen many different terms used on various web pages about repetends such as "non-repeating digits" of the repetend and "prefix" of the repetend.
Personally, I prefer to use "unique digit(s)" of the repetend because that's the term I thought of to best describe the non-repeating part of a repeating decimal number when I started to update a "divide" program I wrote for the TRS-80 Color Computer back in 1989 so that it could find repetends using QB4.5 a few years ago.
So, I guess the short story is that you can call the non-repeating part of a repeating decimal number anything you want to as long as it's within reason / makes sense [it properly describes the digit(s)].
----->>
I guess you have already found that for (1/x), the repetend can be almost any length BUT it will never be greater than (x-1).
(For example, 1 / 7 has a repetend of 6 digits and 1 / 65537 has a repetend of 65536 digits.)
So far as "unique digits", the most I've ever found using 1 divided by a 15 digit number is 48 :
1 / 844,424,930,131,968 = .000000000000001184237892933500309785207112630208333333
(This answer has forty-eight unique digits, and then one digit repeats infinitely.)
There can also be times when the "unique digits" might APPEAR to be the repetend but when the calculation is carried out further the true repetend appears :
10,976.88888888888888877912 / 6 = 1,829.48148148148148146318666666666666666666666
(It looks like "481" will be the repeating pattern at first, but only one digit repeats infinitely.)
The longest TERMINATING decimal number I've found using 1 divided by 15 digits is 49 digits long :
1 / 562,949,953,421,312 = .0000000000000017763568394002504646778106689453125
(This is a 49 digit terminating decimal number.)
----->>
As soon as I can get the program cleaned up a little, I'll upload it. I also need to edit or remove a few references to the .net and .org sites, so it will be at least a few days or more before I can get everything ready.
I'm sure you can easily make use of it to explore repetends and the number of digits required to be checked in order to find them (at least the way I do it).
NOTE : I am not a "professional" mathematician by any means, just someone who became facinated by repeating decimal numbers way back in the 8th grade....
|