Remstart Segan's Calculator Features: -All the normal arithmatic functions (+, -, *, /, ^, sqrt) -Additional built-in functions sin, cos, tan, arcsin, arccos, arctan sqrt, abs, roundup(ceil), rounddown(floor), wrap, factorial -You can use variables (all capital letters are assumed to be variables). assign variables using "store" function. -Enter will repeat last equation. -Use "ans" when you want to use the last answer. -Error catching: Catches most typo style errors -Assumes "*" correctly -Differenciates between when "-" is used as substraction or as a negative sign -Automatically closes all pairs of brackets not already closed. -POWERFUL CONSTANT SYSTEM It works exactly like #constant in DBPro. Search for it in the code for more info. Constants supported: pi, e, m_earth, g Shortcuts supported: asin for arcsin, floor for rounddown, wrapvalue for wrap etc. AND IT'S EASY AS 3.14 TO ADD MORE!!!!! Remend Gosub Init_Constants Gosub Init_Globals While 1 GblError = 0 Input "Equation: ", Eq$ Print " ", Evaluate(Eq$) If GblError = 1 Then cls Endwhile End Function Evaluate(Equation$) Remstart This function will evaluate math equations entered as strings. Features: Remend `I need to add brackets so that the entire question will be solved. If Equation$ = "" Then Equation$ = GblLastEq GblLastEq = Equation$ Equation$ = "("+Equation$+")" `Step 1: Parse the Equation SignNeeded = 0 For x = 1 To Len(Equation$) a$ = Mid$(Equation$, x) `Case: Open Brackets If a$ = "(" If SignNeeded = 1 Then Save_Element("*",Sign) Save_Element("(", oBkt) SignNeeded = 0 inc numopen, 1 Endif `Case: Close brackets If a$ = ")" If SignNeeded = 0 And Endbracketok = 0 Then Error_Message("Error in equation.") Save_Element(")", cBkt) SignNeeded = 1 Endbracketok = 0 inc numclosed, 1 Endif `Case: Basic Sign If a$ = "+" Or a$ = "*" Or a$ = "/" Or a$ = "^" Or (SignNeeded = 1 And a$ = "-") If SignNeeded = 0 Then Error_Message("Illegal use of sign") Save_Element(a$, Sign) SignNeeded = 0 a$ = "done!" `This line is necessary so that two negative signs are not added together. endif `Case: Number If a$ = "." or a$ = "0" or a$ = "1" or a$ = "2" or a$ = "3" or a$ = "4" or a$ = "5" or a$ = "6" or a$ = "7" or a$ = "8" or a$ = "9" or (SignNeeded = 0 And a$ = "-") If SignNeeded = 1 Then Save_Element("*", Sign) tx = x numdone = 0 `Continue reading string until entire number read Repeat inc tx,1 ta$ = Mid$(Equation$, tx) If ta$ = "." or ta$ = "0" or ta$ = "1" or ta$ = "2" or ta$ = "3" or ta$ = "4" or ta$ = "5" or ta$ = "6" or ta$ = "7" or ta$ = "8" or ta$ = "9" or ta$ = " " If ta$ <> " " Then a$ = a$ + ta$ Else x = tx-1 numdone = 1 Endif Until numdone = 1 If a$ = "-" Then a$ = "-1" Save_Element(a$, Num) SignNeeded = 1 endif `Case: lower-case string (either function, constant or command) If lowercase(a$) = 1 If SignNeeded = 1 Then Save_Element("*",Sign) tx = x numdone = 0 `Continue reading string until entire command read Repeat inc tx,1 ta$ = Mid$(Equation$, tx) If lowercase(ta$) = 1 a$ = a$ + ta$ Else numdone = 1 Endif Until numdone = 1 NoError = 0 `Case: Function used For c = 1 To Array Count(Complex(0)) If a$ = Complex(c).Sign x = tx-1 Save_Element(a$, Cpx) NoError = 1 Endif Next C `Case: Constant used For c = 1 To Array Count(Constants(0)) If a$ = Constants(c).Name Equation$ = DeleteItems$(Equation$, x, tx-1) Equation$ = InsertString$(Equation$, x, Constants(c).Value) Dec x, 1 NoError = 1 endif Next c SignNeeded = 0 `Case: Command used For c = 1 To Array Count(Command(0)) If a$ = Command(c).Sign x = tx-1 If a$ = "ans" Then Save_Element(str$(GblLastAns), Num): SignNeeded = 1 If a$ = "store" Delete_Element(Array Count(Element(0))) Repeat inc x, 1: If x > Len(Equation$) Then Error_Message("Error: Illegal use of store function.") a$ = Mid$(Equation$, x) Until a$ <> " " If Uppercase(a$) <> 1 Then Error_Message("Error: Illegal use of store function.") Save_Element(a$, Var) SignNeeded = 0: Endbracketok = 1 a$ = "done" endif NoError = 1 endif next c If NoError = 0 Then Error_Message("Error: TYPO!!!") endif `Case: Variable If Uppercase(a$) = 1 If SignNeeded = 1 Then Save_Element("*", Sign) ascval = asc(a$) -64 Save_Element(str$(Variables(ascval).Value), Num) SignNeeded = 1 endif If GblError = 1 Then Goto Exit_Evaluate_Function next x `Append on any extra brackets that weren't done manually For x = 1 To (numopen-numclosed) Save_Element(")", cBkt) next x `Step 2: Check for brackets and solve each individual part seperately StartBrackets = 1 While StartBrackets <> 0 StartBrackets = Find_e_Type(oBkt, 1) If StartBrackets <> 0 Repeat EndBrackets = Find_e_Type(cBkt, StartBrackets) If EndBrackets = 0 Then Error_Message("Error: No End Brackets"): Goto Exit_Evaluate_Function Check = Find_e_Type(oBkt,StartBrackets+1) If Check < EndBrackets And Check <> 0 Then StartBrackets = Check Until Check <> StartBrackets `Print StartBrackets `Print EndBrackets Solve(StartBrackets+1, EndBrackets-1) `Debug_Array() Delete_Element(StartBrackets) Delete_Element(StartBrackets+1) `Debug_Array() endif EndWhile If Array COunt(Element(0)) > 1 Then Error_Message("Too Many items in array!") ReturnVal# = val(Element(1).e) Delete_Element(1) `If there was an error, exit the function kindly Exit_Evaluate_Function: If GblError = 1 While Array Count(Element(0)) > 0 Delete_Element(1) endwhile ExitFunction 0.0 Endif GblLastAns = ReturnVal# endfunction ReturnVal# Function Solve(Startpos, EndPos) `Do 6 Pases of the equation, checking for each set in the "order of operations." `Pass 1: Check for all complex: ComplexFound = 1 While ComplexFound <> 0 ComplexFound = 0 For pos = Startpos To EndPos If Element(pos).ttype = Cpx e$ = Element(pos).e SolveSimple(pos) ComplexFound = 1 Dec EndPos, 1 Endif next pos endwhile `Pass 2-4: Check for all the other types of stuff For order = 1 To 3 Signfound = 1 While Signfound <> 0 Signfound = 0 For pos = Startpos To EndPos If Element(pos).ttype = Sign e$ = Element(pos).e If (e$= "^" And order = 1) OR (e$ = "*" And order = 2) OR (e$ = "/" And order = 2) OR (e$ = "+" And order = 3) OR (e$ = "-" And order = 3) SolveSimple(pos) Signfound = 1 Dec EndPos, 2 endif Endif Next x Endwhile Next Order `Pass 5: Check for "store" command For pos = Startpos To EndPos If Element(pos).ttype = Var ascval = asc(Element(pos).e)-64 Variables(ascval).value = val(Element(pos-1).e) Delete_Element(pos) Dec EndPos, 1 endif next pos endfunction Function SolveSimple(pos) Local e As String e = Element(pos).e `If Element(pos).ttype <> cpx Then prevnum# = val(Element(pos-1).e) nextnum# = val(Element(pos+1).e) `Step 1: evaluate `i) The basic stuff: If e = "+" Then nextnum# = prevnum# + nextnum# If e = "-" Then nextnum# = prevnum# - nextnum# If e = "*" Then nextnum# = prevnum# * nextnum# If e = "/" Then nextnum# = prevnum# / nextnum# If e = "^" Then nextnum# = prevnum# ^ nextnum# `ii) Trig stuff If e = "sin" Then nextnum# = sin(nextnum#) If e = "cos" Then nextnum# = cos(nextnum#) If e = "tan" Then nextnum# = tan(nextnum#) If e = "arcsin" Then nextnum# = asin(nextnum#) If e = "arccos" Then nextnum# = acos(nextnum#) If e = "arctan" Then nextnum# = atan(nextnum#) `iii) Miscellaneous If e = "sqrt" Then Nextnum# = sqrt(nextnum#) If e = "abs" Then Nextnum# = abs(nextnum#) If e = "roundup" Then Nextnum# = ceil(nextnum#) If e = "rounddown" Then Nextnum# = floor(nextnum#) If e = "wrap" Then Nextnum# = wrapvalue(nextnum#) If e = "factorial" Then Nextnum# = factorial(nextnum#) `Step 2: Replace and delete If Element(pos).ttype = sign Element(pos+1).e = str$(nextnum#) Delete_Element(pos) Delete_Element(pos-1) endif If Element(pos).ttype = cpx Element(pos+1).e = str$(nextnum#) Delete_Element(pos) endif endfunction Function Delete_Element(E_num) Array Delete Element Element(0), E_num endfunction Function Save_Element(element$, e_type) Add to queue Element(0) E_num = Array Count(Element(0)) Element(E_num).e = element$ Element(E_num).ttype = e_type endfunction Function Find_e_Type(etype,start) For x = start To Array Count(Element(0)) If Element(x).ttype = etype Then Exitfunction x next x endfunction 0 Function lowercase(astr$) If Len(astr$) = 1 If asc(astr$) > 96 And asc(astr$) < 123 Then Exitfunction 1 If astr$ = "_" Then ExitFunction 1 Endif endfunction 0 Function uppercase(astr$) If Len(astr$) = 1 If asc(astr$) > 64 AND asc(astr$) < 91 Then Exitfunction 1 endif endfunction 0 Function ExpandMid$(astr$, start, number) Remstart For those who don't have this command already in a DLL (such as IanM's great DLL), or those in the coding competitition, this works! Remend For x = 0 To Number-1 returnvar$ = returnvar$ + Mid$(astr$,start+x) next x endfunction returnvar$ Function DeleteItems$(astr$, d_start, d_end) Remstart Deletes all the items in a string from "start" to "end" Remend newstr$ = ExpandMid$(astr$, 1, d_start-1)+ExpandMid$(astr$, d_end+1, Len(astr$)) endfunction newstr$ Function InsertString$(astr$, start, insert$) newstr$ = ExpandMid$(astr$, 1, start-1)+insert$+ExpandMid$(astr$,start, Len(astr$)) endfunction newstr$ Function Error_Message(txt$) If GblError = 0 cls center text Screen Width()/2, Screen Height()/2, txt$ Sync: Sync Wait Key cls Endif GblError = 1 `Debug_Array() endfunction Function Debug_Array() cls For x = 1 TO Array Count(Element(0)) Print Element(x).ttype, " ", Element(x).e next x Wait Key Endfunction Function factorial(value#) returnval# = 1 For x = 1 To value# returnval# = returnval#*x next x endfunction returnval# `--------------------------------------------------------- Init_Constants: `--------------------------------------------------------- `CONSTANTS `These act just like the #constant command in DBPro. `DBPro: #Constant pi 3.14 `Equation Solver: Data "pi", "3.14" `Notes: `-All constants should be lower-case letters and underscores. ` (All capitals will be interperated as variables.) `-DO NOT use the same word as 2 constants or as a constant and a complex. `-however, "avar" and "var" can both be used. Data "StartConstants" Data "pi", "3.141592654" `pi Data "m_earth", "(5.98*10.0^24.0)" `The mass of the earth Data "g", "9.81" `gravitational feild strength on the surface of the earth Data "e", "2.71828182" Data "asin", "arcsin" Data "acos", "arccos" Data "atan", "arctan" Data "floor", "rounddown" Data "ceil", "roundup" Data "wrapvalue", "wrap" Data "fact", "factorial" Data "a", "ans" Data "s", "store" Data "EndConstants" Type Constant Name As String Value As String endtype Dim Constants(0) As Constant Read TheData$ If TheData$ <> "StartConstants" Then Error_Message("Error: Data is not correct."): End Repeat Read TheData$ If TheData$ <> "EndConstants" Add To Queue Constants(0) C_Num = Array Count(Constants(0)) Constants(C_Num).Name = TheData$ Read TheData$ Constants(C_Num).Value = TheData$ endif until TheData$ = "EndConstants" Type Variable Name As String Value As Float endtype Dim Variables(26) As Variable For x = 1 To 26 ascval = x + 64 Variables(x).Name = str$(ascval) Variables(x).Value = 0.0 next x Return Init_Globals: Global GblError As Boolean: GblError = 0 Global GblLasteq As String Global GblLastAns As Float Type EqElement e As String ttype As Integer endtype Dim Element(0) As EqElement `ttypes of elements Global Num = 1 `1: Num Number Global Sign = 2`2: Sign Sign (Basic sign: +, -, *, /, ^) Global Cpx = 3`3: Cpx Complex (sin, cos, sqrt, log...) Global Var = 4`4: Var Variable (A, B, C, D...) Global oBkt = 5 Global cBkt = 6`5/6: cBkt/oBkt Parenthisis Global Cmd = 7 `7: Cmd Commands (:) Type Operator Sign As String endtype Dim Complex(0) As Operator Read Thedata$ If thedata$ <> "BeginComplex" Then Error_Message("Error: Data is not correct."): End Repeat Read TheData$ If TheData$ <> "EndComplex" Add To Queue Complex(0) C_Num = Array Count(Complex(0)) Complex(C_Num).Sign = TheData$ endif until TheData$ = "EndComplex" Data "BeginComplex" Data "sin" Data "cos" Data "tan" Data "arcsin" Data "arccos" Data "arctan" Data "sqrt" Data "abs" Data "roundup" Data "rounddown" Data "wrap" Data "factorial" Data "EndComplex" Dim Command(0) As Operator Read Thedata$ If Thedata$ <> "BeginCommand" Then Error_Message("Error: Data is not correct."): End Repeat Read TheData$ If TheData$ <> "EndCommand" Add To Queue Command(0) C_Num = Array COunt(Command(0)) Command(C_Num).SIgn = TheData$ endif until THeData$ = "EndCommand" Return Data "BeginCommand" Data "ans" Data "store" Data "EndCommand"