home *** CD-ROM | disk | FTP | other *** search
- {$S+} { Turn on recursion ability, must be first line in Pascal/MT+ }
- {$X+} { Turn on run-time error checking }
-
- Program Handcalc ;
-
- { This program is intended to act as a scientific calculator, with }
- { exponentiation and trancendental functions. }
-
- Const
- Func_Len = 6; { No. of characters allowed in a function name }
- Num_Funcs = 20; { No. of functions recognized }
- Pi = 3.1415926535897323846264338;
-
- Type
- Functions = (ArcTangent, Cosine, Logrithm, Sine, Square, Square_Root,
- Exponent, Tangent, CoTangent, Secant, CoSecant,
- ArcSine, ArcCosine, ArcCotangent, ArcSecant,
- ArcCoSecant, Pie, Radians, Log, Factorial,
- Non_Function);
-
- Set_of_Funcs = Set of Functions;
- Func_Name = array [1..Func_Len] of char;
- Func_Rec = record
- Name : Func_Name;
- Func_Type : Functions
- end;
- Func_List = array [1..Num_Funcs] of Func_Rec;
-
- Var
- Answer : real;
- Buf : String;
- Z : integer; { Index into Buf }
- F_Names : Func_List;
- Non_Parm_Funcs : Set_of_Funcs;
- Debug_Mode : boolean;
-
- Procedure Initialization;
-
- Var
- I : integer;
-
- Procedure Init_Funcs;
-
- begin { Init_Funcs }
- { The order of the strings in F_Names must be alphabetical }
- { This should be remembered when adding new functions }
- F_Names[1].Name := 'ARCCOS'; F_Names[1].Func_Type := ArcCosine;
- F_Names[2].Name := 'ARCCOT'; F_Names[2].Func_Type := ArcCoTangent;
- F_Names[3].Name := 'ARCCSC'; F_Names[3].Func_Type := ArcCoSecant;
- F_Names[4].Name := 'ARCSEC'; F_Names[4].Func_Type := ArcSecant;
- F_Names[5].Name := 'ARCSIN'; F_Names[5].Func_Type := ArcSine;
- F_Names[6].Name := 'ARCTAN'; F_Names[6].Func_Type := ArcTangent;
- F_Names[7].Name := 'COS '; F_Names[7].Func_Type := Cosine;
- F_Names[8].Name := 'COT '; F_Names[8].Func_Type := CoTangent;
- F_Names[9].Name := 'CSC '; F_Names[9].Func_Type := CoSecant;
- F_Names[10].Name:= 'EXP '; F_Names[10].Func_Type:= Exponent;
- F_Names[11].Name:= 'FACTOR'; F_Names[11].Func_Type:= Factorial;
- F_Names[12].Name:= 'LN '; F_Names[12].Func_Type:= Logrithm;
- F_Names[13].Name:= 'LOG '; F_Names[13].Func_Type:= Log;
- F_Names[14].Name:= 'PI '; F_Names[14].Func_Type:= Pie;
- F_Names[15].Name:= 'RADIAN'; F_Names[15].Func_Type:= Radians;
- F_Names[16].Name:= 'SEC '; F_Names[16].Func_Type:= Secant;
- F_Names[17].Name:= 'SIN '; F_Names[17].Func_Type:= Sine;
- F_Names[18].Name:= 'SQR '; F_Names[18].Func_Type:= Square;
- F_Names[19].Name:= 'SQRT '; F_Names[19].Func_Type:= Square_Root;
- F_Names[20].Name:= 'TAN '; F_Names[20].Func_Type:= Tangent;
- Non_Parm_Funcs := [Pie]
- end; { Init_Funcs }
-
- begin { Initialization }
- { Clear the screen }
- For I := 1 to 24 do
- Writeln;
- Writeln ('Calculator');
- Writeln;
- Writeln ('by Warren A. Smith -- July 29, 1981');
- Write (Skip_Line(4));
- Writeln ('A ''?'' at the beginning of a line will bring up a listing');
- Writeln (' of possible functions and operators that may be used.');
- Writeln;
- Writeln ('A dollar sign ''$'' at the beginning of a line will');
- Writeln (' cause this program to terminate.');
- Writeln;
- Debug_Mode := FALSE;
- Init_Funcs
- end; { Initialization }
-
- Function Skip_Line (N : integer) : char;
-
- Var
- I : integer;
-
- begin { Skip_Line }
- For I := 1 to N do
- Writeln;
- Skip_Line := chr(0)
- end; { Skip_Line }
-
- Function Tab (N : integer) : char;
-
- Var
- I : integer;
-
- begin { Tab }
- For I := 1 to N do
- Write (' ')
- end; { Tab }
-
- Function Upper (In_Char : char) : char;
-
- begin { Upper }
- If (In_Char >= 'a') AND (In_Char <= 'z') then
- Upper := chr(ord(In_Char) + (ord('A') - ord('a')))
- else
- Upper := In_Char
- end; { Upper }
-
- Procedure Help;
-
- Var
- Response : char;
-
- begin { Help }
- Write (Skip_Line (24)); { clear the screen }
- Writeln (' The currently available functions are :');
- Writeln;
- Writeln (' ArcCosine - ArcCos ArcCotangent - ArcCot');
- Writeln (' ArcCosecant - ArcCsc ArcSecant - ArcSec');
- Writeln (' ArcSine - ArcSin ArcTangent - ArcTan');
- Writeln (' Cosine - Cos CoTangent - Cot ');
- Writeln (' CoSecant - Csc Natural Exponent - Exp ');
- Writeln (' Natural Log - Ln Secant - Sec ');
- Writeln (' Sine - Sin Square - Sqr ');
- Writeln (' Square Root - Sqrt Tangent - Tan ');
- Writeln (' Log base 10 - Log Factorial - Factor');
- Writeln (' Value of Pi - Pi ');
- Writeln;
- Writeln (' Allowable operators are:');
- Writeln (' ''+'', ''-'', ''*'', ''/'', and ''^'' (exponentiation)');
- Writeln;
- Writeln (' Upper case and lower case are irrelevant in function names');
- Writeln (' A ''$'' will end the program, a ''!'' turns on debug mode ');
- Writeln;
- Writeln ('Hit the carriage return to proceed.');
- Read (Response);
- end; { Help }
-
- Function Eoln : boolean;
-
- begin { Eoln }
- Eoln := Z > Length(Buf)
- end; { Eoln }
-
- Procedure Slough_Blanks;
-
- begin { Slough_Blanks }
- While (Buf[Z] = ' ') AND (not Eoln) do
- Z := Z + 1
- end; { Slough_Blanks }
-
- Procedure Get_Expr;
-
- begin { Get_Expr }
- Repeat
- Writeln;
- Writeln ('Type in an expression to be solved.');
- Readln (Buf);
- Z := 1;
- Slough_Blanks
- Until not Eoln
- end; { Get_Expr }
-
- Function Expr : real;
-
- Var
- Unary,
- Answer : real;
-
- Function Term : real;
-
- Var
- Answer : real;
-
- Function Expon : real;
-
- Var
- Answer : real;
-
- Function XtoY (X, Y : real) : real;
-
- begin { XtoY }
- If X >= 0.0 then
- XtoY := exp(Y * Ln(X))
- else
- XtoY := 0.0
- end; { XtoY }
-
- Function Factor : real;
-
- Var
- Answer,
- X : real;
- Func : Functions;
-
- Procedure Read (Var Answer : real);
-
- Var
- Fact_Power : real;
-
- begin { Read }
- Answer := 0.0;
- Slough_Blanks;
- While Digit (Buf[Z]) AND not Eoln do
- begin
- Answer := Answer * 10.0 + (Ord(Buf[Z])-Ord('0'));
- Z := Z + 1
- end;
- If (Buf[Z] = '.') AND not Eoln then
- begin
- Z := Z + 1;
- Fact_Power := 1.0;
- While Digit (Buf[Z]) AND not Eoln do
- begin
- Fact_Power := Fact_Power / 10.0;
- Answer := Answer+(Ord(Buf[Z])-Ord('0'))*Fact_Power;
- Z := Z + 1
- end
- end
- end; { Read }
-
- Function Digit (In_Char : char) : boolean ;
-
- begin { Digit }
- Digit := In_Char in ['0','1','2','3','4','5','6','7',
- '8','9']
- end; { Digit }
-
- Function Letter (Var In_Char : char) : boolean;
-
- begin { Letter }
- In_Char := Upper (In_Char);
- Letter := In_Char in ['A','B','C','D','E','F','G','H',
- 'I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X',
- 'Y','Z']
- end; { Letter }
-
- Function Get_Func_Type : Functions;
-
- Var
- ID : Func_Name;
- Index : integer;
-
- Function Search_Funcs (ID : Func_Name) : Functions;
-
- Var
- I, J, K : integer;
-
- begin { Search_Funcs }
- I := 1;
- J := Num_Funcs;
- Repeat
- K := (I+J) DIV 2; { Binary search }
- With F_Names[K] do
- begin
- If Name <= ID then
- I := K+1;
-
- If Name >= ID then
- J := K-1
- end
-
- Until I > J;
- If F_Names[K].Name <> ID then
- Search_Funcs := Non_Function
- else
- Search_Funcs := F_Names[K].Func_Type
- end; { Search_Funcs }
-
- begin { Get_Func_Type }
- Index := 1;
- Repeat
- ID [Index] := Buf[Z];
- Z := Z + 1;
- Index := Index + 1
- Until Not Letter(Buf[Z]) OR Eoln OR (Index > Func_Len);
- While Index <= Func_Len do
- begin
- ID [Index] := ' ';
- Index := Index + 1
- end;
-
- Get_Func_Type := Search_Funcs (ID)
- end; { Get_Func_Type }
-
- Function Tan (X : real) : real;
-
- begin { Tan }
- Tan := Sin(X) / Cos(X)
- end; { Tan }
-
- Function Cot (X : real) : real;
-
- begin { Cot }
- Cot := Cos(X) / Sin(X)
- end; { Cot }
-
- Function Sec (X : real) : real;
-
- begin { Sec }
- Sec := 1.0 / Cos(X)
- end; { Sec }
-
- Function Csc (X : real) : real;
-
- begin { Csc }
- Csc := 1.0 / Sin(X)
- end; { Csc }
-
- Function ArcSin (X : real) : real;
-
- begin { ArcSin }
- ArcSin := ArcTan(X / Sqrt(1.0 - Sqr(X)))
- end; { ArcSin }
-
- Function ArcCos (X : real) : real;
-
- begin { ArcCos }
- ArcCos := Pi / 2.0 - ArcTan (X / Sqrt(1.0 - Sqr(X)))
- end; { ArcCos }
-
- Function ArcCot (X : real) : real;
-
- begin { ArcCot }
- ArcCot := Pi / 2.0 - ArcTan (X)
- end; { ArcCot }
-
- Function ArcSec (X : real) : real;
-
- begin { ArcSec }
- ArcSec := ArcTan (Sqrt(Sqr(X) - 1.0))
- end; { ArcSec }
-
- Function ArcCsc (X : real) : real;
-
- begin { ArcCsc }
- ArcCsc := ArcTan (1.0 / Sqrt(Sqr(X) - 1.0))
- end; { ArcCsc }
-
- Function Radian (X : real) : real;
-
- begin { Radian }
- Radian := X * (Pi / 180.0)
- end; { Radian }
-
- Function Log10 (X : real) : real;
-
- begin { Log10 }
- Log10 := Ln(X) / Ln(10.0)
- end; { Log10 }
-
- Function Factorl (X : real) : real;
-
- Var
- Int_X, I : integer;
- Product : real;
-
- begin { Factorl }
- Int_X := Round(X);
- If Int_X = 0 then
- Factorl := 1.0
- else
- begin
- Product := 1.0;
- For I := 2 to Int_X do
- Product := Product * I;
- Factorl := Product
- end
- end; { Factorl }
-
- begin { Factor }
- Slough_Blanks;
- If Digit (Buf[Z]) OR (Buf[Z] = '.') then
- Read (Answer)
- else
- If Buf[Z] = '(' then
- begin
- Z := Z + 1;
- Answer := Expr;
- If Buf[Z] <> ')' then
- begin
- Write (Tab(Z-1),'^ ');
- Writeln ('*** '')'' expected')
- end
- else
- Z := Z + 1
- end
- else
- If Letter (Buf[Z]) then
- begin
- Func := Get_Func_Type;
- Slough_Blanks;
- If not (Func in Non_Parm_Funcs) then
- begin
- If Buf[Z] = '(' then
- begin
- Z := Z + 1;
- Answer := Expr
- end
- else
- begin
- Write (Tab(Z-1), '^ ');
- Write ('*** ''('' expected, answer ');
- Writeln ('may be in error')
- end;
- Slough_Blanks;
- If Buf[Z] = ')' then
- Z := Z + 1
- else
- begin
- Write (Tab(Z-1), '^ ');
- Write ('*** '')'' expected, answer ');
- Writeln ('may be in error')
- end
- end;
- Case Func of
- Logrithm : Answer := Ln (Answer);
- Exponent : Answer := Exp (Answer);
- Log : Answer := Log10 (Answer);
- Square : Answer := Sqr (Answer);
- Square_Root : Answer := Sqrt (Answer);
- Factorial : Answer := Factorl (Answer);
- Cosine : Answer :=
- Cos (Radian(Answer));
- Sine : Answer :=
- Sin (Radian(Answer));
- ArcTangent : Answer :=
- ArcTan (Radian(Answer));
- Tangent : Answer :=
- Tan (Radian(Answer));
- CoTangent : Answer :=
- Cot (Radian(Answer));
- Secant : Answer :=
- Sec (Radian(Answer));
- CoSecant : Answer :=
- Cos (Radian(Answer));
- ArcSine : Answer :=
- ArcSin (Radian(Answer));
- ArcCosine : Answer :=
- ArcCos (Radian(Answer));
- ArcCoTangent: Answer :=
- ArcCot (Radian(Answer));
- ArcSecant : Answer :=
- ArcSec (Radian(Answer));
- ArcCoSecant : Answer :=
- ArcCsc (Answer);
- Pie : Answer := Pi;
- Radians : Answer := Radian (Answer);
- Non_Function: begin
- Write (Tab(Z-1), '^ ');
- Writeln
- ('*** Unknown function name')
- end
- end; { CASE }
- Slough_Blanks
- end
- else
- begin
- Write (Tab(Z-1), '^ ');
- Write ('*** Unknown Syntax, answer may ');
- Writeln ('be in error')
- end;
- If Debug_Mode then
- Writeln ('Result from FACTOR = ', Answer:20:8);
- Factor := Answer
- end; { Factor }
-
- begin { Expon }
- Answer := Factor;
- Slough_Blanks;
- While Buf[Z] = '^' do
- begin
- Z := Z + 1;
- Answer := XtoY (Answer, Factor);
- Slough_Blanks
- end;
- If Debug_Mode then
- Writeln ('Result from EXPON = ', Answer:20:8);
- Expon := Answer
- end; { Expon }
-
- begin { Term }
- Answer := Expon;
- Slough_Blanks;
- While Buf[Z] in ['*', '/'] do
- begin
- If Buf[Z] = '*' then
- begin
- Z := Z + 1;
- Answer := Answer * Expon
- end
- else
- begin
- Z := Z + 1;
- Answer := Answer / Expon;
- end;
- Slough_Blanks
- end;
- If Debug_Mode then
- Writeln ('Result from TERM = ', Answer:20:8);
- Term := Answer
- end; { Term }
-
- begin { Expr }
- Slough_Blanks;
- Unary := 1.0;
- If Buf[Z] in ['+','-'] then
- begin
- If Buf[Z] = '-' then
- Unary := -1.0;
- Z := Z + 1
- end;
- Answer := Unary * Term;
- Slough_Blanks;
- While Buf[Z] in ['+', '-'] do
- begin
- If Buf[Z] = '+' then
- begin
- Z := Z + 1;
- Answer := Answer + Term
- end
- else
- begin
- Z := Z + 1;
- Answer := Answer - Term
- end;
- Slough_Blanks
- end;
- If Debug_Mode then
- Writeln ('Result from EXPR =', Answer:20:8);
- Expr := Answer
- end; { Expr }
-
- begin { Main }
- Initialize;
- Get_Expr;
- While Buf[Z] <> '$' do
- begin
- If Buf[Z] = '?' then
- Help
- else
- If Buf[Z] = '!' then
- Debug_Mode := not Debug_Mode
- else
- If Buf[Z] <> '$' then
- begin
- Answer := Expr;
- Write ('The answer is ');
- Write ( Answer:9:6 );
- Writeln
- end;
- Get_Expr
- end;
- Writeln;
- Writeln ('Program ended');
- Writeln
- end.
-