Just finished calculating pi to 30 trillion places. - Pete - 08-15-2022
And guess what, it is a repetend at decimal place 14 trillion, 678 billion, 36!
Okay, so I may be exaggerating a little. In reality, I think pi has been calculated to around 10-trillion non-repeating places. Now what the super computers use for that, I haven't looked up. The old school method uses something like this...
1/1 - 1/3 + 1/5 - 1/7 + 1/9... pi/4
It took me a few hours using 750 iterations to get the 3.14 part finally right. I suspect it would take several thousand iterations to get to 3.14159. Anyway, it was a neat way to see how my string math routine would hold up. Below is what I used, but set to just 40 iterations to make the demo speed tolerable and only 150 places. It only gets as far as: 3.11659
Code: (Select All) DIM SHARED betatest%: betatest% = -1
WIDTH 160, 42
_SCREENMOVE 0, 0
limit&& = 500
j = -1
FOR i = 1 TO 40
j = j + 2
IF oldd$ = "" THEN
d$ = "1": oldd$ = "1": oldn$ = "1": n$ = "1"
ELSE
d$ = LTRIM$(STR$(j))
' 2nd denominator * 1st numerator.
a$ = d$: b$ = oldn$: op$ = "*"
CALL string_math(a$, op$, b$, x$, limit&&)
m1$ = x$
' 1st denominator * 2nd numerator.
a$ = oldd$: b$ = n$
CALL string_math(a$, op$, b$, x$, limit&&)
m2$ = x$
' Get common denominator
a$ = d$: b$ = oldd$
CALL string_math(a$, op$, b$, x$, limit&&)
d$ = x$
a$ = m1$: b$ = m2$: IF i / 2 = i \ 2 THEN op$ = "-" ELSE op$ = "+"
CALL string_math(a$, op$, b$, x$, limit&&)
REM PRINT "oldn$ = "; oldn$; " oldd$ = "; oldd$, "n$ = "; x$; " d$ = "; d$
PRINT "n$ = "; x$; " d$ = "; d$;: COLOR 14, 0: PRINT j: COLOR 7, 0
oldn$ = x$: oldd$ = d$
END IF
NEXT
REM CALL greatest_common_factor(x$, d$, limit&&) ' Too slow.
n$ = x$
a$ = x$: b$ = d$: op$ = "/"
' Speed up processing by liiting each calculated iteration t 16 places.
' Remove thiss condition to retain accuracy.
IF LEN(a$) > 16 THEN
j = LEN(a$)
k = LEN(b$)
i = j - k
a$ = MID$(a$, 1, 16 + i): b$ = MID$(b$, 1, 16)
END IF
CALL string_math(a$, op$, b$, x$, limit&&)
a$ = x$: b$ = "4": op$ = "*"
CALL string_math(a$, op$, b$, x$, limit&&)
PRINT: PRINT "pi = "; x$
END
SUB string_math (stringmatha$, operator$, stringmathb$, runningtotal$, limit&&)
SELECT CASE operator$
CASE "+", "-"
GOTO string_add_subtract
CASE "*"
GOTO string_multiply
CASE "/"
GOTO string_divide
CASE ELSE
PRINT "Error, no operator selected. operator$ = "; operator$
END SELECT
string_divide:
divsign% = 0: divremainder& = 0: divremainder$ = "": divplace& = 0: 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: 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$ = ""
IF stringmathb$ = "overflow" THEN divsign% = 0: operationdivision% = 0: EXIT SUB
runningtotal$ = stringmathb$: stringmathb$ = ""
IF divsign% THEN runningtotal$ = "-" + runningtotal$
IF stringmathround$ <> "" THEN runningtotal$ = runningtotal$ + stringmathround$
operationdivision% = 0
EXIT SUB
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 charater 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$ = ""
IF stringmathb$ = "overflow" THEN EXIT SUB
runningtotal$ = stringmathb$: stringmathb$ = ""
IF m_sign% THEN runningtotal$ = "-" + runningtotal$: m_sign% = 0
EXIT SUB
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)
GOSUB string_comp
IF gl% < 0 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)
GOSUB string_comp
IF gl% < 0 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)
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
IF stringmathb$ = "overflow" THEN n2sign$ = "": EXIT SUB
runningtotal$ = n2sign$ + stringmathb$: n2sign$ = ""
EXIT SUB
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
string_comp:
DO
REM Remove trailing zeros after a decimal point.
IF INSTR(acomp$, ".") THEN
DO UNTIL RIGHT$(acomp$, 1) <> "0" AND RIGHT$(acomp$, 1) <> "." AND RIGHT$(acomp$, 1) <> "-"
acomp$ = MID$(acomp$, 1, LEN(acomp$) - 1)
LOOP
END IF
IF INSTR(bcomp$, ".") THEN
DO UNTIL RIGHT$(bcomp$, 1) <> "0" AND RIGHT$(bcomp$, 1) <> "." AND RIGHT$(bcomp$, 1) <> "-"
bcomp$ = MID$(bcomp$, 1, LEN(bcomp$) - 1)
LOOP
END IF
IF MID$(acomp$, 1, 2) = "-0" OR acomp$ = "" OR acomp$ = "-" THEN acomp$ = "0"
IF MID$(bcomp$, 1, 2) = "-0" OR bcomp$ = "" OR bcomp$ = "-" THEN bcomp$ = "0"
' A - and +
IF LEFT$(acomp$, 1) = "-" THEN j% = -1
IF LEFT$(bcomp$, 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(acomp$, ".")
k% = INSTR(bcomp$, ".")
IF j% = 0 AND k% THEN
IF acomp$ = "0" THEN gl% = -1 ELSE gl% = 1
EXIT DO
END IF
IF k% = 0 AND j% THEN
IF bcomp$ = "0" THEN gl% = 1 ELSE gl% = -1
EXIT DO
END IF
' Both decimals.
IF j% THEN
IF acomp$ > bcomp$ THEN
gl% = 1
ELSEIF acomp$ = bcomp$ THEN gl% = 0
ELSEIF acomp$ < bcomp$ THEN gl% = -1
END IF
EXIT DO
END IF
' Both positive or both negative whole numbers.
SELECT CASE LEN(acomp$)
CASE IS < LEN(bcomp$)
gl% = -1
CASE IS = LEN(bcomp$)
IF acomp$ = bcomp$ THEN
gl% = 0
ELSEIF acomp$ > bcomp$ THEN gl% = 1
ELSEIF acomp$ < bcomp$ THEN gl% = -1
END IF
CASE IS > LEN(bcomp$)
gl% = 1
END SELECT
EXIT DO
LOOP
RETURN
END SUB
SUB greatest_common_factor (gfca$, gfcb$, limit&&)
hold_gfca$ = gfca$
hold_gfcb$ = gfcb$
numerator$ = gfca$: denominator$ = gfcb$
' Make both numbers positive.
IF MID$(gfca$, 1, 1) = "-" THEN gfca$ = MID$(gfca$, 2)
IF MID$(gfcb$, 1, 1) = "-" THEN gfcb$ = MID$(gfcb$, 2)
GOSUB string_comp
IF gl% THEN SWAP gfca$, gfcb$
DO
stringmatha$ = gfca$: stringmathb$ = gfcb$
operator$ = "/": CALL string_math(stringmatha$, operator$, stringmathb$, runningtotal$, limit&&)
IF INSTR(runningtotal$, ".") THEN runningtotal$ = MID$(runningtotal$, 1, INSTR(runningtotal$, ".") - 1)
stringmatha$ = runningtotal$: stringmathb$ = gfcb$
operator$ = "*": CALL string_math(stringmatha$, operator$, stringmathb$, runningtotal$, limit&&)
stringmatha$ = gfca$: stringmathb$ = runningtotal$
operator$ = "-": CALL string_math(stringmatha$, operator$, stringmathb$, runningtotal$, limit&&)
SWAP gfca$, gfcb$: gfcb$ = runningtotal$
IF runningtotal$ = "0" THEN EXIT DO
LOOP
stringmatha$ = numerator$: stringmathb$ = gfca$
operator$ = "/": CALL string_math(stringmatha$, operator$, stringmathb$, runningtotal$, limit&&)
numerator$ = runningtotal$
stringmatha$ = denominator$: stringmathb$ = gfca$
operator$ = "/": CALL string_math(stringmatha$, operator$, stringmathb$, runningtotal$, limit&&)
denominator$ = runningtotal$
IF betatest% THEN
PRINT "GFC = "; gfca$; ": Previous fraction: "; hold_gfca$; " / "; hold_gfcb$, "Reduced: "; numerator$; " / "; denominator$
END IF
gfca$ = numerator$: gfcb$ = denominator$
EXIT SUB
string_comp:
DO
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
RETURN
END SUB
The slowest part of the string math is division. It would be nice to find a way to divide with fewer steps.
Note: For more accuracy, increase the limit&& to 500 or more.
EDIT: Forgot to mention I put in condition to spped it up after 70 iteratins, but the trade off is loss of accuracy. Remove this condition if accuracy is desired over speed, but wow, after a few hundred loops the numbers get so large the calculations take a lot of time.
' Speed up processing by liiting each calculated iteration t 16 places.
' Remove thiss condition to retain accuracy.
IF LEN(a$) > 16 THEN
j = LEN(a$)
k = LEN(b$)
i = j - k
a$ = MID$(a$, 1, 16 + i): b$ = MID$(b$, 1, 16)
END IF
Pete
RE: Just finished calculating pi to 30 trillion places. - Coolman - 08-15-2022
thank you for sharing this code, I will do a test with qb64 compiled in O3 and without.
RE: Just finished calculating pi to 30 trillion places. - Kernelpanic - 08-15-2022
@Pete, I think your path is a dead end. There are several formulas for calculating pi, one of which seems quite workable to me - if the program works. It is the formel by Ramanujan.
Maybe someone will find the error in the calculation?
Ramanujan’s Formula for Pi and Kreiszahl Wikipedia - below
Code: (Select All) 'pi berechnen - 15. Aug. 2022
Dim n As Integer
Dim pi, pir, x As Double
Dim rampi As _Integer64
Print
pir = Sqr(2) * (9801 / 4412)
Print Using "pi SR = ###.########"; pir
Print
n = 2
'Nach Wikipedia - Ramanujan -- correct
pi = (Sqr(n) * (9801) / (4412))
Print Using "Wiki pi = ###.#######"; pi
Print
'Where is the mistake?
pi = (0.0002885855652225477 + (24 * (1103 + 26390)) / (1 * 24591257856))
Print Using "Ramanu ausgerechnet pi = ###.#######"; pi
Print
pi = (Sqr(8) / 9801) + ((24 * (1103 + 26390)) / (1 * (396 ^ 4)))
Print Using "Ramanu pi = ###.#######"; pi
Print
x = 396 ^ 4
Print "x = "; x
RE: Just finished calculating pi to 30 trillion places. - Pete - 08-15-2022
I haven't researched what super-computers use to calculate pi, but my guess, after testing is that Leibniz formula isn't it! Of course if the one you posted actually has a flaw, it wouldn't be used, either.
I'm not planning on using this to calculate pi accurately at all. I thought it would be fun to throw together, since some of a different discussion thread evolved into a discussion about pi. I also realized this would be a great stress test for my string math routine.
Pete
RE: Just finished calculating pi to 30 trillion places. - JRace - 08-15-2022
An infinite series like Leibniz will get you there, but you might want to grab some coffee (as in "Drive out to Starbucks. Take your time, enjoy the day.") while you wait. (https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Convergence)
There are definitely faster ways of calculating Pi.
If you REALLY want to know, maybe see how its done by y-cruncher or mini-pi by Alexander Yee (https://github.com/Mysticial).
Once upon a time I experimented with using Taylor series for trig functions. I thought I had a Pi calculator in the bunch as well, but I'm not finding it in my archives.
Ugh. My morning caffeine hasn't kicked in yet and all this math is making my head hurt.
355/113 is usually all I need for Pi.
Edited to add: https://cs.uwaterloo.ca/~alopez-o/math-faq/mathtext/node12.html
And the work of super-programmer Fabrice Bellard: https://bellard.org/pi/pi2700e9/
Alright dammit, this is my last edit: https://en.wikipedia.org/wiki/Approximations_of_%CF%80#20th_and_21st_centuries
RE: Just finished calculating pi to 30 trillion places. - Kernelpanic - 08-15-2022
(08-15-2022, 05:13 PM)Pete Wrote: I haven't researched what super-computers use to calculate pi, but my guess, after testing is that Leibniz formula isn't it! Of course if the one you posted actually has a flaw, it wouldn't be used, either.
Pete
Ramanujan's formula is guaranteed to be correct, only my translation into a computer program has an error.
I'm not a mathematician, but Rama's formula seems to me to be very elegant and powerful - if a hobbyist can turn it into a working program.
Let's see, today I won't do anything more. Maybe tomorrow . . .
RE: Just finished calculating pi to 30 trillion places. - Pete - 08-15-2022
@JRace
LOL, I know how you feel. Take a mathpirin with that java!
To my credit, I don't get overly caught up in any fanciful fixation that I and QB64 will break the world record in pi calc. Everyone knows you need FreeBASIC and a truck load of hallucinogenics for that!
That second to last link was a fun read. While using atan(x) = x - x^3/3 + x^5/5 seems simple enough, I haven't expanded my string math routines for trigonometric functions. That's another reason why I stopped shopping when I found Leibniz method, and converted it to code. Simple multiplication and division of fractions.
The history link was an interesting read, too. Thanks!
@Kernelpanic
In the link JRace provided we find:
"A third one comes from the theory of complex multiplication of elliptic curves, and was discovered by S. Ramanujan. This gives a number of beautiful formulas, but the most useful was missed by Ramanujan and discovered by the Chudnovsky's. It is the following (slightly modified for ease of programming): "
This is probably what you were challenging others to find in your previous post.
Pete
RE: Just finished calculating pi to 30 trillion places. - JRace - 08-15-2022
@KernelPanic: the first constant:
0.0002885855652225477 is being stored into pi as:
0.0002885855792555958
Edited to add: also, (Sqr(8) / 9801) = 0.0002885855792555958 according to QB64.
WolframAlpha says it's: 0.00028858556522254775
RE: Just finished calculating pi to 30 trillion places. - Kernelpanic - 08-15-2022
(08-15-2022, 06:55 PM)Pete Wrote: @Kernelpanic
In the link JRace provided we find:
"A third one comes from the theory of complex multiplication of elliptic curves, and was discovered by S. Ramanujan. This gives a number of beautiful formulas, but the most useful was missed by Ramanujan and discovered by the Chudnovsky's. It is the following (slightly modified for ease of programming): "
This is probably what you were challenging others to find in your previous post.
Pete
@Pete, I've read about Chudnovsky too, but as long as I can't put Ramanujan into a computer program, it'll stay where it is. Its formula is even more complicated.
I'm all about calculating PI myself, and not competing with the freaks who use supercomputers.
By the way, Pete, do you know y-cruncher? If yes is ok, if not - try it out. But watch what you do.
y-cruncher - A Multi-Threaded Pi-Program
RE: Just finished calculating pi to 30 trillion places. - Pete - 08-15-2022
(08-15-2022, 07:28 PM)JRace Wrote: @KernelPanic: the first constant:
0.0002885855652225477 is being stored into pi as:
0.0002885855792555958
Edited to add: also, (Sqr(8) / 9801) = 0.0002885855792555958 according to QB64.
WolframAlpha says it's: 0.00028858556522254775
I haven't programmed square roots for string math yet, but with a precision calculator, sqrt(8) = 2.8284271247461900976
so with string math: 2.8284271247461900976 / 9801=0.00028858556522254775
0.00028858556522254775 (String math)
0.0002885855792555958 (QB64 reported by JRice)
0.00028858556522254775 (WolframAlpha)
So I would concur WolframAlpha is correct.
Pete
|