home *** CD-ROM | disk | FTP | other *** search
- '**************************************************************************************************
- '* *
- '* ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ *
- '* SCANNER, PARSER & EVALUATOR FOR MATHEMATICAL FUNCTIONS *
- '* ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ *
- '* *
- '* WAHT IT DOES: *
- '* ------------- *
- '* Anyone, who ever wanted to give in a mathematical expression in runtime (i. e. not the direct *
- '* way in the program code itself) knows, that this is a very hard job, because when you give in *
- '* such an expression while your program is running, it will treat your expression as if it was *
- '* any normal kind of text string. But what it should do is just 'understand' your formular. *
- '* So you have have to establish a small (sometimes it can get really big, of course!) interpre- *
- '* ter for mathematical formulas with brackets, operator hierarchie or only for normal number *
- '* chrunching, perhaps for your own calculator. That's just what it does! *
- '* *
- '* HOW TO WRITE FORMULAS: *
- '* ---------------------- *
- '* These routines read and analyse any mathematical expression in Infix notation and evaluate it. *
- '* You can use one variable x, any of the operators +, -, *, /, ^ and use up to 10 levels of *
- '* brackets. Within each level 10 brackets on the same level are allowed. You can use *
- '* many special mathematical functions which are predefined inside this program for your own *
- '* use. Furthermore can you input the symbols '╣' and 'e', they are converted to their real *
- '* values. It is possible to use any of the three kinds of Brackets (), [] and {}. The program *
- '* will treat them all the same. *
- '* A special feature is the treatment of the '*' operator in conjunction with variables and *
- '* functions. You are allowed to omit this operator in all those special cases where the normal *
- '* mathematical conventions allow you to do it. Here is a list of all those special cases, in *
- '* which you don't need the '*' operator. You can omit '*' between: *
- '* a) values (left) and x: 2x = 2*x *
- '* b) x and x: xx = x*x *
- '* c) values (left) and brackets: 2(x-4) = of 2*(x-4) *
- '* d) x and brackets (both sides): x(3-x) or (3-x)x = x*(3-x) or (3-x)*x *
- '* e) brackets: (x-2)(x+4) = (x-2)*(x+4) *
- '* f) values (left) and functions: 4sin(x) = 4*sin(x) *
- '* g) x and functions (both sides): xln(x) or ln(x)x = x*ln(x) or ln(x)*x *
- '* h) brackets and functions (both sides): (2-x)cos(x) = (2-x)*cos(x) *
- '* i) functions and funktions: sin(x)cos(x) = sin(x)*cos(x) *
- '* The following cases are not supported (you also should not use them in normal mathematical *
- '* notation, because it leads to misunderstandings): (x-4)3¡(x-4)*3, x2¡x*2, ln(x)4¡ln(x)*4 ! *
- '* You can use negative Exponents with the '^' operator without brackets: x^-3 = x^(-3). *
- '* You are allowed to write with small letters or with capital letters or all mixed up, it does *
- '* not matter at all, because the input expression will be converted to capital letters anyway. *
- '* At least there are no problems with any number of spaces between symbols and values. They all *
- '* will be truncated just at the beginning of the program. *
- '* I think this additions will please anyone who is used to write mathematical expressions. You *
- '* can do it just the way you used to do. *
- '* I didn't implement lot's of error routines because you should create them for your special *
- '* program needs (may be you use special filter functions in FUTURE Basic etc.). So please *
- '* take care of those things when you use this code for your own purpose. *
- '* *
- '* GENERAL NOTICE AND COPYRIGHT: *
- '* ----------------------------- *
- '* Though I'm no friend of any special code ownership (I know about some 'shareware' programmers *
- '* who take money for their code.) you first should be aware that I worked very hard to get this *
- '* peace of software do what it should do. I'm no novice but I'm still learning and learning... *
- '* So my understanding of this kind of general programming roundtables is, that we all together *
- '* should share our own ideas with others, so that we can learn from each other. I don't like *
- '* these special guys who always want to hide their ideas from others. It's only a matter of *
- '* time that another will have the same inspiration and solve this programming problems anyway. *
- '* But there is one situation in which I think you should be honest and give some contribution to *
- '* the author of programming code, that is when you go commercial with you program and use parts *
- '* or whole units of programming code from other authors. On the other hand I'm always interes- *
- '* ted in your opinion about what I have done. And believe me, I will always try to do just the *
- '* same and give you my response when I took some peace of code from you. So please give me some *
- '* response, otherwise it's useless for me to be a member of CompuServe, because in that case *
- '* this information service whould only be a special kind of grocery store for me. *
- '* Thanks for your patience to follow me so far. *
- '* Detlef Reimers *
- '* 2000 Hamburg 61, Suentelstrasse 7 (Germany) *
- '* CompuServe #1100015,1146 *
- '* *
- '* PRINTING THIS CODE: *
- '* ------------------- *
- '* I have a 15 inch monitor and therefore this text has a great width. If you want to print it *
- '* out fine, just choose 90% scaling and letter size and everything will fit into the page width. *
- '**************************************************************************************************
-
- WINDOW OFF:WINDOW 1,"Parser",(2,40)-(637,860),257
-
- ' -----------------------------------------------------------------------------------------------
-
- "Start"
-
- DIM Op$(30) ' operators & functions
- DIM T$(10,10) ' sub expressions in brackets
- DIM 16 Z$(10,10,20) ' strings for values and x
- DIM 2 O$(10,10,20) ' original operators
- DIM 2 P$(10,10,20) ' temporèry operators
- DIM N!(10,10,20) ' original values
- DIM M!(10,10,20) ' temporèry values
- DIM Num(10,10) ' number of values inside the brackets
- DIM K(10) ' number of brackets
- DIM F&(48) ' math functions
- DIM N(4) ' string positions
- DIM N$(2) ' search strings
-
-
- ' -----------------------------------------------------------------------------------------------
-
- DATA SIN, COS, TAN, COT, SINH, COSH, TANH, COTH, ASIN, ACOS, ATAN, ACOT
- DATA ASINH, ACOSH, ATANH, ACOTH, LN, EXP, SQR, FAK, INT, FRAC, ABS, SGN
- DATA A, B, C, D, F, G, H, I, J, K, L, M
- DATA N, O, P, Q, R, S, T, U, V, W, Y, Z
-
- ' -----------------------------------------------------------------------------------------------
-
- RESTORE
-
- FOR I=1 TO 48
- READ PSTR$(F&(I))
- NEXT I
-
- FOR I=25 TO 48
- Op$(I-24)=PSTR$(F&(I))
- NEXT I
-
- Op$(25)="^":Op$(26)="^":Op$(27)="*":Op$(28)="/":Op$(29)="+":Op$(30)="-"
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Term
-
- Term$=UCASE$(Term$)
-
- LONG IF LEN(Term$)>1
- DO
- Len=LEN(Term$)
- N=INSTR(1,Term$," ")
- LONG IF N
- Term$=LEFT$(Term$,N-1)+RIGHT$(Term$,Len-N)
- END IF
- UNTIL N=0
-
- Len=LEN(Term$)
-
- FOR I=1 TO 4
-
- DO
- N(1)=INSTR(1,Term$,"[")
- N(2)=INSTR(1,Term$,"{")
- N(3)=INSTR(1,Term$,"]")
- N(4)=INSTR(1,Term$,"}")
- LONG IF N(I)
- IF I<3 THEN MID$(Term$,N(I),1)="(" ELSE MID$(Term$,N(I),1)=")"
- END IF
- UNTIL N(I)=0
-
- NEXT I
-
- FOR I=1 TO 2
-
- DO
- FOR J=1 TO Len
- Len=LEN(Term$)
- N(1)=INSTR(J,Term$,"X")
- N(2)=INSTR(J,Term$,"(")
- N$=MID$(Term$,N(I)-1,1)
- LONG IF (N$>="0" AND N$<="9") OR N$="X" OR N$=")"
- IF N(I)>1 THEN Term$=LEFT$(Term$,N(I)-1)+"*"+RIGHT$(Term$,Len-(N(I)-1))
- END IF
- NEXT J
- UNTIL (N$<"0" OR N$>"9") AND N$<>"X" AND N$<>")"
-
- NEXT I
- END IF
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Substitute
-
- LONG IF LEN(Term$)>2
- FOR I=24 TO 1 STEP -1
- S$=PSTR$(F&(I))
- LenS=LEN(S$)
-
- DO
- Len=LEN(Term$)
- N=INSTR(1,Term$,S$)
- LONG IF N
- Term$=LEFT$(Term$,N-1)+"1"+PSTR$(F&(I+24))+RIGHT$(Term$,Len-LenS-(N-1))
- END IF
- UNTIL N=0
-
- NEXT I
-
- FOR I=1 TO 26
- LONG IF CHR$(64+I)<>"X" AND CHR$(64+I)<>"E"
-
- DO
- FOR J=1 TO Len
- Len=LEN(Term$)
- N=INSTR(J,Term$,CHR$(64+I))
- N$=MID$(Term$,N-2,1)
- LONG IF (N$>="0" AND N$<="9") OR N$="X" OR N$=")"
- IF N>2 THEN Term$=LEFT$(Term$,N-2)+"*"+RIGHT$(Term$,Len-(N-2))
- END IF
- NEXT J
- UNTIL (N$<"0" OR N$>"9") AND N$<>"X" AND N$<>")"
-
- END IF
- NEXT I
- END IF
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Brackets
-
- Max=1
- Auf=0
- Zu=0
- S=1
- K(1)=1
- Length=LEN(Term$)
-
- FOR I=1 TO Length
- S$=MID$(Term$,I,1)
-
- SELECT S$
- CASE "("
- T$(S,K(S))=T$(S,K(S))+"Ñ"
- Auf=Auf+1
- S=S+1
- K(S)=K(S)+1
- IF S>Max THEN Max=S
- CASE ")"
- Zu=Zu+1
- S=S-1
- CASE ELSE
- T$(S,K(S))=T$(S,K(S))+S$
- END SELECT
-
- NEXT I
-
- IF Auf<>Zu THEN PRINT "Bracket error":BEEP:GOTO "New"
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Scanner
-
- FOR S=1 TO Max
- FOR N=1 TO K(S)
-
- J=1:K=1
- Length=LEN(T$(S,N))
- Z$(N,S,J)=""
-
- FOR I=1 TO Length
- S$=MID$(T$(S,N),I,1)
-
- LONG IF VAL(S$) OR S$="0" OR S$="." OR S$="X" OR S$="╣" OR S$="E" OR S$="Ñ"
-
- IF I=2 AND MID$(T$(S,N),1,1)="-" THEN Z$(S,N,J)="-"+Z$(S,N,J)
- IF MID$(T$(S,N),I-2,2)="^-" THEN Z$(S,N,J)="-"+Z$(S,N,J)
- Z$(S,N,J)=Z$(S,N,J)+S$
-
- LONG IF Z$(S,N,J)="E" OR Z$(S,N,J)="-E" OR Z$(S,N,J)="╣" OR Z$(S,N,J)="-╣"
- IF Z$(S,N,J)= "E" THEN N!(S,N,J)= 2.718281828
- IF Z$(S,N,J)="-E" THEN N!(S,N,J)=-2.718281828
- IF Z$(S,N,J)= "╣" THEN N!(S,N,J)= 3.141592654
- IF Z$(S,N,J)="-╣" THEN N!(S,N,J)=-3.141592654
- XELSE
- N!(S,N,J)=VAL(Z$(S,N,J))
- END IF
-
- XELSE
-
- LONG IF S$="+" OR S$="-" OR S$="*" OR S$="/" OR S$="^"
- LONG IF MID$(T$(S,N),I-1,1)<>"^" AND I<>1
- O$(S,N,K)=S$
- K=K+1
- END IF
- XELSE
- LONG IF S$>="A" AND S$<="Z"
- O$(S,N,K)=S$
- K=K+1
- XELSE
- PRINT "Variable error":BEEP:GOTO "New"
- END IF
- END IF
-
- LONG IF Z$(S,N,J)<>""
- J=J+1
- END IF
-
- END IF
-
- NEXT I
- Num(S,N)=J
-
- NEXT N
- NEXT S
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Fak(n)
-
- LONG IF n=0
- Fak=1
- XELSE
- Fak=n*FN Fak(n-1)
- END IF
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Function
-
- FOR L=1 TO 29 STEP 2
- I=0
-
- DO
- I=I+1
-
- LONG IF P$(S,N,I)=Op$(L) OR P$(S,N,I)=Op$(L+1)
- X1!=M!(S,N,I):X2!=M!(S,N,I+1)
-
- SELECT P$(S,N,I)
- CASE "+"
- M!(S,N,I)=X1!+X2!
- CASE "-"
- M!(S,N,I)=X1!-X2!
- CASE "*"
- M!(S,N,I)=X1!*X2!
- CASE "/"
- M!(S,N,I)=X1!/X2!
- CASE "^"
- M!(S,N,I)=X1!^X2!
- CASE "A"
- M!(S,N,I)=SIN(X2!) 'sin
- CASE "B"
- M!(S,N,I)=COS(X2!) 'cos
- CASE "C"
- M!(S,N,I)=TAN(X2!) 'tan
- CASE "D"
- M!(S,N,I)=1/TAN(X2!) 'cot
- CASE "F"
- M!(S,N,I)=(EXP(X2!)-EXP(-X2!))/2 'sinh
- CASE "G"
- M!(S,N,I)=(EXP(X2!)+EXP(-X2!))/2 'cosh
- CASE "H"
- M!(S,N,I)=(EXP(X2!)-1)/(EXP(X2!)+1) 'tanh
- CASE "I"
- M!(S,N,I)=(EXP(X2!)+1)/(EXP(X2!)-1) 'coth
- CASE "J"
- M!(S,N,I)=ATN(X2!/SQR(1-X2!*X2!)) 'arcsin
- CASE "K"
- M!(S,N,I)=ATN(1)*2-ATN(X2!/SQR(1-X2!*X2!)) 'arccos
- CASE "L"
- M!(S,N,I)=ATN(X2!) 'arctan
- CASE "M"
- M!(S,N,I)=ATN(1)*2-ATN(X2!) 'arccot
- CASE "N"
- M!(S,N,I)=LOG(X2!+SQR(X2!*X2!+1)) 'arcsinh
- CASE "O"
- M!(S,N,I)=LOG(X2!+SQR(X2!*X2!-1)) 'arccosh
- CASE "P"
- M!(S,N,I)=LOG((1+X2!)/(1-X2!))/2 'arctanh
- CASE "Q"
- M!(S,N,I)=LOG((X2!+1)/(X2!-1))/2 'arctanh
- CASE "R"
- M!(S,N,I)=LOG(X2!) 'ln x
- CASE "S"
- M!(S,N,I)=EXP(X2!) 'e^x
- CASE "T"
- M!(S,N,I)=SQR(X2!) 'square root
- CASE "U"
- M!(S,N,I)=FN Fak(X2!) 'fakultèt
- CASE "V"
- M!(S,N,I)=INT(X2!) 'integer
- CASE "W"
- M!(S,N,I)=FRAC(X2!) 'fraction
- CASE "Y"
- M!(S,N,I)=ABS(X2!) 'absolut
- CASE "Z"
- M!(S,N,I)=SGN(X2!) 'signum
- CASE ELSE
- PRINT "Operator error":BEEP:GOTO "New"
- END SELECT
-
- old&=VARPTR(M!(S,N,I+2))
- max&=VARPTR(M!(S,N,Nmax))
- new&=VARPTR(M!(S,N,I+1))
- Length=max&-old&+4
- BLOCKMOVE old&,new&,Length
-
- old&=VARPTR(P$(S,N,I+1))
- max&=VARPTR(P$(S,N,Nmax))
- new&=VARPTR(P$(S,N,I))
- Length=max&-old&+3
- BLOCKMOVE old&,new&,Length
-
- Nmax=Nmax-1
- I=0
-
- END IF
-
- UNTIL I>=Nmax-1
-
- NEXT L
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Parser
-
- FOR S=Max TO 1 STEP -1
- W=0
- FOR N=1 TO K(S)
-
- FOR J=1 TO Num(S,N)
-
- SELECT Z$(S,N,J)
- CASE "X"
- N!(S,N,J)=x!
- CASE "-X"
- N!(S,N,J)=-x!
- CASE "Ñ"
- W=W+1
- N!(S,N,J)=M!(S+1,W,1)
- CASE "-Ñ"
- W=W+1
- N!(S,N,J)=-M!(S+1,W,1)
- END SELECT
-
- Nmax=Num(S,N)
- old&=VARPTR(N!(S,N,1))
- max&=VARPTR(N!(S,N,Nmax))
- new&=VARPTR(M!(S,N,1))
- Length=max&-old&+4
- BLOCKMOVE old&,new&,Length
-
- old&=VARPTR(O$(S,N,1))
- max&=VARPTR(O$(S,N,Nmax-1))
- new&=VARPTR(P$(S,N,1))
- Length=max&-old&+3
- BLOCKMOVE old&,new&,Length
-
- FN Function
-
- NEXT J
-
- NEXT N
- NEXT S
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Print
-
- CLS
- PRINT
- PRINT In$
- PRINT STRING$(LEN(Term$),"-")
- PRINT
-
- FOR S=1 TO Max
-
- FOR N=1 TO K(S)
- PRINT T$(S,N),"=";M!(S,N,1)
- FOR I=1 TO Num(S,N)
- PRINT S;N;I,Z$(S,N,I);STRING$(20-POS(0)," ");O$(S,N,I)
- NEXT I
- PRINT STRING$(21,"-")
- NEXT N
-
- NEXT S
-
- PRINT "X","=";x!
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- LONG FN Evaluate
-
- CLS
- PRINT
- PRINT In$
- PRINT STRING$(LEN(Term$),"-")
- PRINT
- PRINT "Input a value (Return quits, e and ╣ possible)"
- PRINT
- INPUT "X=";X$
-
- IF X$="" THEN "New"
- IF X$="╣" OR X$="╕" THEN X$="3.141592654"
- IF X$="e" OR X$="E" THEN X$="2.718281828"
- x!=VAL(X$)
-
- FN Parser
- FN Print
-
- DO
- UNTIL MOUSE(3) OR LEN(INKEY$)
-
- FN Evaluate
-
- END FN
-
- ' -----------------------------------------------------------------------------------------------
-
- "Input"
-
- CLS
- PRINT
- PRINT "Please input expression (Return quits)"
- PRINT
- INPUT "Term: ";Term$
- IF Term$="" THEN END
-
-
- FN Term
- FN Substitute
- In$=Term$
- FN Brackets
- FN Scanner
- FN Evaluate
-
- "New"
- CLS
- CLEAR
- PRINT
- PRINT "New formula? (y / n) ";
- DO
- I$=INKEY$
- UNTIL I$<>""
- IF I$="y" OR I$="Y" THEN "Start"
-
- END
-