Just a thought :)

Chris,
did you ever have in mind to include arbitrary precision arithmetics in SB?
Of course, not in code, nor a genuine one (as in Liberty Basic), but linked to external gmp.lib. AFAIK, there are libraries for all platforms, including Android...
I understand it is a huge work behind it, but due to flexibility of string and array functions in SB, IMHO, it would be possible...

As I wrote above, only a thought

Cheers

Arbitrary long integers might be all that is needed with +-* operations. In JB, I just finished a fractions calculator that keeps maths in perfect precision for +-* and / operations and could calculate e constant to 50 decimal places with such tools. (JB has arbitrary long integer for +-*)

That reminds me, I wanted to see if there were a Taylor series for roots.

I have often thought about doing what figosdev claims to have done. I wonder if subtraction is not so very different than addition. You would need addition to do multiplication. I wonder about doing it just for integers. hmm...

"How arbitrary is arbitrary?"

Long as it takes? Well I know from e constant calculation, the factorials were getting quite ridiculous at 42, there's your answer, 42!

a spoiler mark, what i did was loop (from right to left) through each string, convert each place to integer, and (one step at a time, just like by hand) do the steps you would do to add the long numbers on paper-- carry the 1 and everything.

i did it as an animation so that you could watch each step, including carry the one. but obviously for an everyday function youd want to take out the delay and the display on the screen, and just add the numbers.

as to whether subtraction is the same-- almost.

you know as well as i do, that subtraction involves borrowing instead.

addition is the easiest. im sure many of us are up to the task if we become interested enough. best of all, it can all be done in basic (though i would surely use fig.)

Just off the desktop so may have bugs. I already see some little nonsense about a check if i is greater than length of an operand string. That part was written before I made both strings the same length and never removed. Doesn't hurt the results though.


' String Add.bas SmallBASIC 0.12.8 [B+=MGA] 2017-03-16

label restart 'test arith with small random numbers and ops
a = str(rand(-10, 10))
b = str(rand(-10, 10))
if rand(0, 1) then ops = "+" :ans = val(a) + val(b) else ops = "-": ans = val(a) - val(b)
? a;" ";ops;" ";b;" is:"
s = arith(a, ops, b)
? "arith returned ";s
? " Compare to ";ans
input "Press just enter to see another checked test, for long string tests press any + enter ";OK
if len(OK) then goto longStrings else goto restart

label longStrings
a = longStr()
b = longStr()
if rand(0, 1) then ops = "+" else ops = "-"
? right(space(60)+a, 60);" ";ops
? right(space(60)+b, 60);" ";"="
? right(space(60)+arith(a, ops, b), 60)
input "OK enter, quit = any + enter ";OK
if len(OK) then end else goto longStrings

'this is ugly long!!!
'This takes care of number signs and correct call to adds or subtracs
func arith(a, op, b) 'all strings arguments, op = + or -
local sa, aa, sb, bb, agtb, r
'this decides the sign in final answer and which function to call for arith
if left(a, 1) = "-" then sa = 1 : aa = mid(a, 2) else sa = 0 : aa = a
if left(b, 1) = "-" then sb = 1 : bb = mid(b, 2) else sb = 0 : bb = b
'? "sa ";sa;" aa ";aa
'? "sb ";sb;" bb ";bb
if len(aa) > len(bb) then
agtb = 1
elseif len(aa) < len(bb)
agtb = 0
elseif len(aa) = len(bb)
for i = 1 to len(aa)
if val(mid(aa, i, 1)) > val(mid(bb, i, 1)) then
agtb = 1 :exit for
elseif val(mid(aa, i, 1)) < val(mid(bb, i, 1))
agtb = 0 : exit for
end if
next
else
agtb = 0
end if
if op = "+" then
'? "op is ";op
'? "agtb is ";agtb
if sa = sb then '-10 + -5 or 10 + 5
if sa then r = "-" + adds(aa, bb) else r = adds(aa, bb)
else
if agtb = 1 then
if sa = 1 then ' -10 + 5
r = "-" + subtracs(aa, bb)
elseif sb = 1 ' 10 + -5
r = subtracs(aa, bb)
end if
else 'b gt a and signs are different
if sa = 1 then ' -5 + 10
r = subtracs(bb, aa)
elseif sb = 1 ' 5 + -10
r = "-" + subtracs(bb, aa)
end if
end if
end if
elseif op = "-"
'? "op is ";op
'? "agtb is ";agtb
if sa = 1 and sb = 1 then
if agtb then '-10 - -5
r = "-" + subtracs(aa, bb)
else '-5 - -10
r = subtracs(bb, aa)
end if
elseif sa = 1 and sb = 0 ' -5 - 10 or -10 - 5
r = "-" + adds(aa, bb)
elseif sa = 0 and sb = 1 ' 5 - -10 or 10 - -5
r = adds(aa, bb)
elseif sa = 0 and sb = 0
if agtb then '10 - 5
r = subtracs(aa, bb)
else ' 5 - 10
r = "-" + subtracs(bb, aa)
end if
end if
end if
if r = "-0" then r = "0"
arith = r
end

func
adds(j, k) 'add two POSITIVE integers in string form
'assuming just 2 big integers in string form, no decimals
local m, b, i, cj, ck, t, cc, co
m = max(len(j), len(k)) : b = ""
j = right(string(m, "0") + j, m)
k = right(string(m, "0") + k, m)
for i = m to 1 step -1
if i <= len(j) then cj = val(mid(j, i, 1)) else cj = 0
if i <= len(k) then ck = val(mid(k, i, 1)) else ck = 0
t = str(cj + ck + co)
cc = mid(t, len(t), 1)
if len(t) > 1 then co = val(mid(t, 1, len(t)-1)) else co = 0
b = cc + b
next
if co > 0 then b = str(co) + b
while left(b, 1) = "0" and len(b) > 1 : b = mid(b, 2) : wend
adds = b
end

func
subtracs(j, k) 'subtract a lesser positive integer from a greater j>k
'assuming just 2 big integers in string form, no decimals
local m, b, i, cj, ck, t, w
m = max(len(j), len(k)) : b = ""
j = right(string(m, "0") + j, m)
k = right(string(m, "0") + k, m)
for i = m to 1 step -1
if i <= len(j) then cj = val(mid(j, i, 1)) else cj = 0
if i <= len(k) then ck = val(mid(k, i, 1)) else ck = 0
if cj < ck then
t = str(10 + cj - ck)
'borrow 1 = rewrite string
w = i - 1
while w > 0 and mid(j, w, 1) = "0"
mids j, w, "9"
w = w - 1
wend
if w > 0 then mids j, w, str( val(mid(j, w, 1)) - 1 )
else
t = str(cj - ck)
end if
b = t + b
next
while left(b, 1) = "0" and len(b) > 1 : b = mid(b, 2) : wend
subtracs = b
end


sub
mids(byref source, position, replacement)
local b, i
b = ""
for i = 1 to len(source)
if i = position then
b = b + replacement
else
b = b + mid(source, i, 1)
end if
next
source = b
end

func
rand(n1, n2)
local hi, lo
if n1 > n2 then hi = n1 : lo = n2 else hi = n2 : lo = n1
rand = (rnd * (hi - lo + 1)) \ 1 + lo
end


func
longStr()
local l, s, b
l = rand(20, 50) : b = ""
for i = 1 to l
b = b + mid("0123456789", rand(1, 10), 1)
next
while left(b, 1) = "0" and len(b) > 1 : b = mid(b, 2) : wend
if rand(0, 1) then b = "-" + b
longStr = b
end


Onto being fruitful... ;-))

;-)) 1 hour and 40 mins until this day is over, can I get mult done also?

Multiply wasn't bad but got hung up by not clearing a carry over when there wasn't one.


' String Add.bas SmallBASIC 0.12.8 [B+=MGA] 2017-03-16
'add, subtract, and multiply!

'? mults("9999", "9")
'pause
'end

label restart 'test arith with small random numbers and ops
a = str(rand(-10000, 10000))
b = str(rand(-10000, 10000))
rop = rand(0, 2)
'rop = 2
select case rop
case 0 : ops = "+" : ans = val(a) + val(b)
case 1 : ops = "-" : ans = val(a) - val(b)
case 2 : ops = "*" : ans = val(a) * val(b)
end select
? a;" ";ops;" ";b;" is:"
s = arith(a, ops, b)
? "arith returned ";s
? " Compare to ";ans
input "Press just enter to see another checked test, for long string tests press any + enter ";OK
if len(OK) then goto longStrings else goto restart

label longStrings
a = longStr()
b = longStr()
rop = rand(0, 2)
select case rop
case 0 : ops = "+" : ans = val(a) + val(b)
case 1 : ops = "-" : ans = val(a) - val(b)
case 2 : ops = "*" : ans = val(a) * val(b)
end select
? right(space(80)+a, 80);" ";ops
? right(space(80)+b, 80);" ";"="
? right(space(80)+arith(a, ops, b), 80)
input "OK enter, quit = any + enter ";OK
if len(OK) then end else goto longStrings

'this is ugly long!!!
'This takes care of number signs and correct call to adds or subtracs
func arith(a, op, b) 'all strings arguments, op = + or -
local sa, aa, sb, bb, agtb, r
'this decides the sign in final answer and which function to call for arith
if left(a, 1) = "-" then sa = 1 : aa = mid(a, 2) else sa = 0 : aa = a
if left(b, 1) = "-" then sb = 1 : bb = mid(b, 2) else sb = 0 : bb = b
'? "sa ";sa;" aa ";aa
'? "sb ";sb;" bb ";bb
if len(aa) > len(bb) then
agtb = 1
elseif len(aa) < len(bb)
agtb = 0
elseif len(aa) = len(bb)
for i = 1 to len(aa)
if val(mid(aa, i, 1)) > val(mid(bb, i, 1)) then
agtb = 1 :exit for
elseif val(mid(aa, i, 1)) < val(mid(bb, i, 1))
agtb = 0 : exit for
end if
next
else
agtb = 0
end if
if op = "+" then
'? "op is ";op
'? "agtb is ";agtb
if sa = sb then '-10 + -5 or 10 + 5
if sa then r = "-" + adds(aa, bb) else r = adds(aa, bb)
else
if agtb = 1 then
if sa = 1 then ' -10 + 5
r = "-" + subtracs(aa, bb)
elseif sb = 1 ' 10 + -5
r = subtracs(aa, bb)
end if
else 'b gt a and signs are different
if sa = 1 then ' -5 + 10
r = subtracs(bb, aa)
elseif sb = 1 ' 5 + -10
r = "-" + subtracs(bb, aa)
end if
end if
end if
elseif op = "-"
'? "op is ";op
'? "agtb is ";agtb
if sa = 1 and sb = 1 then
if agtb then '-10 - -5
r = "-" + subtracs(aa, bb)
else '-5 - -10
r = subtracs(bb, aa)
end if
elseif sa = 1 and sb = 0 ' -5 - 10 or -10 - 5
r = "-" + adds(aa, bb)
elseif sa = 0 and sb = 1 ' 5 - -10 or 10 - -5
r = adds(aa, bb)
elseif sa = 0 and sb = 0
if agtb then '10 - 5
r = subtracs(aa, bb)
else ' 5 - 10
r = "-" + subtracs(bb, aa)
end if
end if
elseif op = "*"
if sa = sb then r = mults(aa, bb) else r = "-" + mults(aa, bb)
end if
if r = "-0" then r = "0"
arith = r
end

func
mults(y, z) 'two positive integer strings
local iy, iz, b1, b2
b2 = "0"
for iz = len(z) to 1 step -1
if iz < len(z) then b1 = string(len(z) - iz, "0") else b1 = ""
co = 0
for iy = len(y) to 1 step -1
t = str(val(mid(z, iz, 1)) * val(mid(y, iy,1)) + co)
b1 = right(t, 1) + b1
if len(t) > 1 then co = val(mid(t, 1, len(t)-1)) else co = 0
next
if co > 0 then b1 = str(co) + b1
'? "b1, b2 = ";b1;", ";b2
b2 = adds(b2, b1)
'? "b2 new = ";b2
next
mults = b2
end


func
adds(j, k) 'add two POSITIVE integers in string form
'assuming just 2 big integers in string form, no decimals
local m, b, i, cj, ck, t, cc, co
m = max(len(j), len(k)) : b = ""
j = right(string(m, "0") + j, m)
k = right(string(m, "0") + k, m)
for i = m to 1 step -1
if i <= len(j) then cj = val(mid(j, i, 1)) else cj = 0
if i <= len(k) then ck = val(mid(k, i, 1)) else ck = 0
t = str(cj + ck + co)
cc = mid(t, len(t), 1)
if len(t) > 1 then co = val(mid(t, 1, len(t)-1)) else co = 0
b = cc + b
next
if co > 0 then b = str(co) + b
while left(b, 1) = "0" and len(b) > 1 : b = mid(b, 2) : wend
adds = b
end

func
subtracs(j, k) 'subtract a lesser positive integer from a greater j>k
'assuming just 2 big integers in string form, no decimals
local m, b, i, cj, ck, t, w
m = max(len(j), len(k)) : b = ""
j = right(string(m, "0") + j, m)
k = right(string(m, "0") + k, m)
for i = m to 1 step -1
if i <= len(j) then cj = val(mid(j, i, 1)) else cj = 0
if i <= len(k) then ck = val(mid(k, i, 1)) else ck = 0
if cj < ck then
t = str(10 + cj - ck)
'borrow 1 = rewrite string
w = i - 1
while w > 0 and mid(j, w, 1) = "0"
mids j, w, "9"
w = w - 1
wend
if w > 0 then mids j, w, str( val(mid(j, w, 1)) - 1 )
else
t = str(cj - ck)
end if
b = t + b
next
while left(b, 1) = "0" and len(b) > 1 : b = mid(b, 2) : wend
subtracs = b
end


sub
mids(byref source, position, replacement)
local b, i
b = ""
for i = 1 to len(source)
if i = position then
b = b + replacement
else
b = b + mid(source, i, 1)
end if
next
source = b
end

func
rand(n1, n2)
local hi, lo
if n1 > n2 then hi = n1 : lo = n2 else hi = n2 : lo = n1
rand = (rnd * (hi - lo + 1)) \ 1 + lo
end


func
longStr()
local l, s, b
l = rand(20, 40) : b = ""
for i = 1 to l
b = b + mid("0123456789", rand(1, 10), 1)
next
while left(b, 1) = "0" and len(b) > 1 : b = mid(b, 2) : wend
if rand(0, 1) then b = "-" + b
longStr = b
end

Working on division, I have encountered crossroads for decisions.

To maintain perfect precision, I have left the Remainder part intact, so 13 / 12 = 1 R:1
or I could write it as 1_1/12
and 26/24 could be reduced to same 1_1/12, they can be reduced because I have both MOD and GCD working for string Math.

So one crossroad or decision point is which format is more satisfactory?

The other crossroad is when converting to decimal, you more often than not sacrifice perfect precision as 1/12 expressed in decimal form even to 100 places is infinitely less precise than 1_1/12.

Oh! writing this out here, I just discovered 1 R:1 is incomplete! R:1 what???? You need the 12, so 1_1/12 IS BETTER expression of 13 divided by 12, perfect and complete.

SO! the 4 main operations of arithmetic can be maintained, perfectly precise. Basically because any number you write down to operate on has to be finite.

add 1 R:1 and 3 R:3 == ??? R:... lacks info

but

add 1_1/3 and 3_3/5 == 4_14/15 see? more info

The second form serves as a complete number and perfect compared to any decimal expansion.

it depends on how it is called.

if you call your division routine with 1234567890987654321 / 5, then we all know r:1 means "and 1/5."

if you get two numbers from a file and divide the two, we only know what r:1 means if we open the file.

so youre right-- at least sometimes. and its probably best to put /5 after the 1.