This is a set of functions that can be used in the rare cases where you need to calculate mathematical operations as exact as possible. Here is a list of the functions you can use:
string = Add(string, string)
string = Subtract(string, string)
string = Multiply(string, string)
string = Divide(string, string)
string = Square_root(string)
Since division can result in a number with an infinite decimal, you may specify how accurate you want the calculation to be via the math.sigfig variable which will limit division calculations to a certain number of significant figures.
Of course, the numbers are passed to and returned from the functions in strings in order to preserve accuracy. The numbers can be virtually any size, not limited to the size of floats or dwords.
The square root algorithm is very slow as it must do repeated division, multiplication, and addition.
The sigfig parameter only applies to division and square roots. Addition, Subtraction, and Multiplication are not affected by the sigfig value in any way.
There are a few known bugs:
Sometimes the division used to put the decimal place in the wrong spot. I really just hacked the algorithm together, so if you find 2 numbers that don't divide right, let me know and I'll try to figure out how to fix it. I think it is fixed and division works fine for most numbers but there's a chance it pops up again.
The square root function doesn't always return the right answer. For example, it returns 2.9999999999999999 (up to math.sigfig decimal places) for the square root of 9.
Here are the functions:
sync on
sync rate 0
cls
set window on
set display mode 1024,768,32
type math
number1 as string
number2 as string
sigfig
endtype
global math as math
`This represents the maximum amount of significant figures the result of the division function can have.
math.sigfig=20
REM here are some example calculations that are evaluated when you execute the program:
print "1234.234+1234.1=",add("1234.234","1234.1")
sync
print "9563+23452.345=",add("9563","23452.345")
sync
print "1234.234-1234.1=",subtract("1234.234","1234.1")
sync
print "9563--23452.345=",subtract("9563","-23452.345")
sync
print "2*2234=",multiply("2","2234")
sync
print "10*50.5=",multiply("-10","50.5")
sync
print "234/-2234=",divide("234","-2234")
sync
print "(1234-12412423+12412423)*124234.1/124234.1=",divide(multiply(add(subtract("1234","12412423"),"12412423"),"124234.1"),"124234.1")
sync
print "1000/3=",divide("1000","3")
sync
print "1234/65=",divide("1234","65")
sync
print "2345.235/8785634.4=",divide("2345.235","8785634.4")
sync
print "10001000100010001000100010001000.1000100*12.34=",multiply("10001000100010001000100010001000.1000100","12.34")
sync
print "sqrt(1)=",square_root("1")
sync
print "sqrt(2)=",square_root("2")
sync
print "sqrt(3)=",square_root("3")
sync
print "sqrt(4)=",square_root("4")
sync
print "sqrt(5)=",square_root("5")
sync
print "sqrt(6)=",square_root("6")
sync
print "sqrt(7)=",square_root("7")
sync
print "sqrt(8)=",square_root("8")
sync
print "sqrt(9)=",square_root("9")
sync
print "done"
sync
sync
wait key
end
function add(number1$,number2$)
while left$(number1$,1)="+" or left$(number1$,1)="-"
if left$(number1$,1)="-" then number1sign=1-number1sign
number1$=right$(number1$,len(number1$)-1)
endwhile
while left$(number2$,1)="+" or left$(number2$,1)="-"
if left$(number2$,1)="-" then number2sign=1-number2sign
number2$=right$(number2$,len(number2$)-1)
endwhile
_align(number1$,number2$)
if number1sign=number2sign
result$=_add(math.number1,math.number2)
if number1sign=1
result$="-"+result$
endif
else
g=_greater(math.number1,math.number2)
if g=0
exitfunction "0."
endif
if g=1
result$=_subtract(math.number1,math.number2)
if number1sign=1
result$="-"+result$
endif
endif
if g=2
result$=_subtract(math.number2,math.number1)
if number2sign=1
result$="-"+result$
endif
endif
endif
endfunction result$
function subtract(number1$,number2$)
REM subtraction is adding the opposite.
result$=add(number1$,"-"+number2$)
endfunction result$
function multiply(number1$,number2$)
REM This function accepts 2 real numbers
while left$(number1$,1)="+" or left$(number1$,1)="-"
if left$(number1$,1)="-" then number1sign=1-number1sign
number1$=right$(number1$,len(number1$)-1)
endwhile
while left$(number2$,1)="+" or left$(number2$,1)="-"
if left$(number2$,1)="-" then number2sign=1-number2sign
number2$=right$(number2$,len(number2$)-1)
endwhile
number1$=clean(number1$)
number2$=clean(number2$)
resultsign=abs(number1sign-number2sign)
decimal1=len(number1$)+1
for n=1 to len(number1$)
if mid$(number1$,n)="."
decimalplaces=len(number1$)-n
number1$=left$(number1$,n-1)+right$(number1$,len(number1$)-n)
endif
next n
for n=1 to len(number2$)
if mid$(number2$,n)="."
decimalplaces=decimalplaces+len(number2$)-n
number2$=left$(number2$,n-1)+right$(number2$,len(number2$)-n)
endif
next n
result$=_multiply(number1$,number2$)
if resultsign=1
result$="-"+result$
endif
result$=clean(left$(result$,len(result$)-decimalplaces)+"."+right$(result$,decimalplaces))
endfunction result$
function divide(number1$,number2$)
REM This function accepts 2 real numbers
while left$(number1$,1)="+" or left$(number1$,1)="-"
if left$(number1$,1)="-" then number1sign=1-number1sign
number1$=right$(number1$,len(number1$)-1)
endwhile
while left$(number2$,1)="+" or left$(number2$,1)="-"
if left$(number2$,1)="-" then number2sign=1-number2sign
number2$=right$(number2$,len(number2$)-1)
endwhile
number1$=clean(number1$)
number2$=clean(number2$)
if number2$="0." then exitfunction "Error: Cannot divide by zero!"
resultsign=abs(number1sign-number2sign)
decimal1=len(number1$)+1
for n=1 to len(number1$)
if mid$(number1$,n)="."
decimalplaces=len(number1$)-n
number1$=left$(number1$,n-1)+right$(number1$,len(number1$)-n)
endif
next n
for n=1 to len(number2$)
if mid$(number2$,n)="."
decimalplaces=decimalplaces-(len(number2$)-n)
number2$=left$(number2$,n-1)+right$(number2$,len(number2$)-n)
endif
next n
REM Long Division Algorithm
divisor$=number2$
dividend$=number1$
de=decimalplaces
if de<0 then de=0
if de>1 then de=1
for digit=1 to math.sigfig+de
while len(dividend$)-(digit-1)<len(divisor$)
dividend$=dividend$+"0"
inc decimalplaces
endwhile
if digit=1
difference$=left$(dividend$,len(divisor$))
else
difference$=difference$+mid$(dividend$,digit+len(divisor$)-1)
endif
mult=1
product$=divisor$
do
_align(product$,difference$)
g=_greater(math.number1,math.number2)
if g<>2 then exit
inc mult
product$=multiply(divisor$,str$(mult))
loop
if g=1
if mult=1
result$=result$+"0"
mult=0
else
dec mult
product$=multiply(divisor$,str$(mult))
endif
endif
newlevel=1
if mult>0
result$=result$+str$(mult)
else
newlevel=0
endif
if newlevel=1
difference$=removechar(subtract(difference$,product$),".")
endif
next digit
result$=repstr("0",200)+result$
result$=clean(left$(result$,len(result$)-decimalplaces)+"."+right$(result$,decimalplaces))
if resultsign=1
result$="-"+result$
endif
endfunction result$
function square_root(number1$)
number1$=clean(number1$)
if number1$="1." then exitfunction "1."
result$="2.0"
repeat
if left$(result$,len(result$)-2)=left$(oldresult$,len(result$)-2) then inc c
oldresult$=result$
result$=divide(number1$,oldresult$)
result$=add(result$,oldresult$)
result$=divide(result$,"2.0")
until left$(result$,len(result$)-2)=left$(oldresult$,len(result$)-2) and c>2
endfunction result$
function _add(number1$,number2$)
REM Addition Algorithm
REM This function takes two aligned unsigned numbers and returns the sum.
carry=0
result$=""
for n=len(number1$) to 1 step -1
if mid$(number1$,n)="."
result$="."+result$
else
sum=val(mid$(number1$,n))+val(mid$(number2$,n))+carry
carry=0
if sum>9
carry=1
sum=sum-10
endif
result$=str$(sum)+result$
endif
next n
if carry=1
result$="1"+result$
endif
result$=clean(result$)
endfunction result$
function _subtract(number1$,number2$)
REM Subtraction Algorithm
REM This function takes two aligned unsigned numbers where the first number is greater than the second and returns the difference.
borrow=0
result$=""
for n=len(number1$) to 1 step -1
if mid$(number1$,n)="."
result$="."+result$
else
if val(mid$(number1$,n))-borrow>=val(mid$(number2$,n))
result$=str$(val(mid$(number1$,n))-borrow-val(mid$(number2$,n)))+result$
borrow=0
else
result$=str$(10+val(mid$(number1$,n))-borrow-val(mid$(number2$,n)))+result$
borrow=1
endif
endif
next n
result$=clean(result$)
endfunction result$
function _multiply(number1$,number2$)
REM This function assumes that the numbers are sign-less and contain no decimal points.
REM This uses the Karatsuba algorithm
if len(number1$)<5 and len(number2$)<5
exitfunction str$(val(number1$)*val(number2$))
endif
if len(number1$)/2.0<>int(len(number1$)/2.0)
number1$="0"+number1$
endif
if len(number2$)/2.0<>int(len(number2$)/2.0)
number2$="0"+number2$
endif
while len(number1$)<len(number2$)
number1$="0"+number1$
endwhile
while len(number2$)<len(number1$)
number2$="0"+number2$
endwhile
m=len(number1$)/2
number1a$=left$(number1$,m)
number1b$=right$(number1$,m)
number2a$=left$(number2$,m)
number2b$=right$(number2$,m)
A$=_multiply(number1a$,number2a$)
B$=_multiply(number1b$,number2b$)
C$=_multiply(removechar(add(number1a$,number1b$),"."),removechar(add(number2a$,number2b$),"."))
D$=removechar(subtract(subtract(C$,A$),B$),".")
result$=removechar(add(add(A$+repstr("0",m*2),D$+repstr("0",m)),B$),".")
endfunction result$
function _align(number1$,number2$)
REM This function assumes there are no signs in front of either of the numbers.
decimal1=len(number1$)+1
for n=1 to len(number1$)
if mid$(number1$,n)="."
decimal1=n
endif
next n
decimal2=len(number2$)+1
for n=1 to len(number2$)
if mid$(number2$,n)="."
decimal2=n
endif
next n
if decimal1=len(number1$)+1 then number1$=number1$+"."
if decimal2=len(number2$)+1 then number2$=number2$+"."
while decimal1>decimal2
number2$="0"+number2$
inc decimal2
endwhile
while decimal2>decimal1
number1$="0"+number1$
inc decimal1
endwhile
while len(number1$)<len(number2$)
number1$=number1$+"0"
endwhile
while len(number2$)<len(number1$)
number2$=number2$+"0"
endwhile
math.number1=number1$
math.number2=number2$
endfunction
function clean(number$)
REM This function removes any extra zeros and makes sure there is a decimal point in the string.
REM This function assumes there is no sign in front of the number.
while left$(number$,1)="0":number$=right$(number$,len(number$)-1):endwhile
contains_decimal=0
for n=1 to len(number$)
if mid$(number$,n)="."
contains_decimal=1
endif
next n
if contains_decimal=0
number$=number$+"."
endif
while right$(number$,1)="0":number$=left$(number$,len(number$)-1):endwhile
if number$="." then number$="0."
endfunction number$
function removechar(strg$,char$)
result$=""
for n=1 to len(strg$)
if mid$(strg$,n)<>char$
result$=result$+mid$(strg$,n)
endif
next n
endfunction result$
function _greater(number1$,number2$)
for n=1 to len(number1$)
if val(mid$(number1$,n))>val(mid$(number2$,n))
exitfunction 1
endif
if val(mid$(number2$,n))>val(mid$(number1$,n))
exitfunction 2
endif
next n
endfunction 0
function repstr(strg$,amt)
result$=""
for n=1 to amt
result$=result$+strg$
next n
endfunction result$