Parsing/RPN calculator algorithm: Difference between revisions

→‎{{header|QuickBASIC}}: Added a solution.
(→‎{{header|ANSI Standard BASIC}}: Simplifications: 1. In get_number, buffer for conversion is not necessary. 2. In is_digit, used the parameter ch$ instead of a global variable. Added result in Decimal BASIC.)
(→‎{{header|QuickBASIC}}: Added a solution.)
Line 1,088:
 
Result:3.00012207
</pre>
 
==={{header|QuickBASIC}}===
{{trans|Java|In fact, stack and tokenizing had to be implemented. Converting string to numbers is based on the <code>VAL</code> function in BASIC.}}
Supports multi-digit numbers and negative numbers.
<syntaxhighlight lang="qbasic">
' Parsing/RPN calculator algorithm
DECLARE SUB MakeEmpty (S AS ANY)
DECLARE SUB Push (X AS SINGLE, S AS ANY)
DECLARE SUB PrintStack (S AS ANY)
DECLARE SUB EvalRPN (Expr$)
DECLARE FUNCTION Empty% (S AS ANY)
DECLARE FUNCTION Pop! (S AS ANY)
 
CONST MAXINDEX = 63
 
TYPE TNumStack
TopIndex AS INTEGER
Elems(MAXINDEX) AS SINGLE
END TYPE
 
EvalRPN ("3 4 2 * 1 5 - 2 3 ^ ^ / +")
END
 
FUNCTION Empty% (S AS TNumStack)
Empty% = S.TopIndex > MAXINDEX
END FUNCTION
 
SUB EvalRPN (Expr$)
DIM S AS TNumStack
MakeEmpty S
PRINT "Input", "Operation", "Stack after"
' SP% - start position of token
' DP% - position of delimiter
DP% = 0
DO
SP% = DP% + 1
DP% = INSTR(DP% + 1, Expr$, " ")
IF DP% <> 0 THEN
TE% = DP% - 1
Token$ = MID$(Expr$, SP%, DP% - SP%)
ELSE
Token$ = MID$(Expr$, SP%, LEN(Expr$) - SP% + 1)
END IF
PRINT Token$,
IF Token$ = "*" THEN
PRINT "Operate",
Second = Pop(S): First = Pop(S)
Push First * Second, S
ELSEIF Token$ = "/" THEN
PRINT "Operate",
Second = Pop(S): First = Pop(S)
Push First / Second, S
ELSEIF Token$ = "-" THEN
PRINT "Operate",
Second = Pop(S): First = Pop(S)
Push First - Second, S
ELSEIF Token$ = "+" THEN
PRINT "Operate",
Second = Pop(S): First = Pop(S)
Push First + Second, S
ELSEIF Token$ = "^" THEN
PRINT "Operate",
Second = Pop(S): First = Pop(S)
Push First ^ Second, S
ELSE
PRINT "Push",
Push VAL(Token$), S
END IF
PrintStack S
LOOP UNTIL DP% = 0
PRINT "Final answer: "; Pop(S)
IF NOT Empty(S) THEN
PRINT "Error, too many operands: ";
PrintStack S
STOP
END IF
END SUB
 
SUB MakeEmpty (S AS TNumStack)
S.TopIndex = MAXINDEX + 1
END SUB
 
FUNCTION Pop (S AS TNumStack)
IF Empty%(S) THEN
PRINT "The stack is empty."
STOP
ELSE
Pop = S.Elems(S.TopIndex)
S.TopIndex = S.TopIndex + 1
END IF
END FUNCTION
 
SUB PrintStack (S AS TNumStack)
FOR Ptr% = S.TopIndex% TO MAXINDEX
PRINT USING "######.###"; S.Elems(Ptr%);
NEXT Ptr%
PRINT
END SUB
 
SUB Push (X AS SINGLE, S AS TNumStack)
IF S.TopIndex = 0 THEN
PRINT "The stack is full."
STOP
ELSE
S.TopIndex = S.TopIndex - 1
S.Elems(S.TopIndex) = X
END IF
END SUB
</syntaxhighlight>
{{out}}
<pre>
Input Operation Stack after
3 Push 3.000
4 Push 4.000 3.000
2 Push 2.000 4.000 3.000
* Operate 8.000 3.000
1 Push 1.000 8.000 3.000
5 Push 5.000 1.000 8.000 3.000
- Operate -4.000 8.000 3.000
2 Push 2.000 -4.000 8.000 3.000
3 Push 3.000 2.000 -4.000 8.000 3.000
^ Operate 8.000 -4.000 8.000 3.000
^ Operate 65536.000 8.000 3.000
/ Operate 0.000 3.000
+ Operate 3.000
Final answer: 3.000122
</pre>
 
512

edits