Hello, if you have any need, please feel free to consult us, this is my wechat: wx91due
Lab5: CASIO-fx991
1. Background and Objective
CASIO-fx991, one of the best calculators in the world, excels at calculating mathematical expressions, making it indispensable for us to survive engineering courses. However, have you ever been curious about how CASIO "understands" the expressions and gets the right answers? In this Lab, you will figure this out and create a CASIO fx991 calculator program on your computer with C programming language. In the future, you can combine this algorithm with other hardware to make a real calculator on your own.
Now, your objective is to read commands from a .txt file, and you need to parse these commands and output the results line by line.
2. Syntax and Rules
2.1. Basic Operators
Notice that " ^ " in C is not the meaning of power. You may use pow() in math.h
The output can all be a " double " type
input(in commands.txt):
stdout:
Notice that you need to consider possible spaces between the operator and numbers, as well as multiple parentheses.
You need to use Reverse Polish Expression and the stack data structure to parse and interpret the expressions, which will be covered in part 4 of this file.
2.2. Variables and Assignment Operator(" = ")
input(in commands.txt):
stdout:
input:
stdout:
359.532104
2.4. Restrictions
1. We promise that there won't be any syntax errors in the test cases, so you can suppose all the commands in "commands.txt" are valid.
4. Reverse Polish Expression
4.1 The Stack Data Structure
1. Push: Add a new element to the end of the stack
Therefore, with these two basic operations, a stack has the property of "First in, Last out" (FILO), thus changing the order of the added elements.
Then, in order to support the stack data structure, you have to prepare two things: one is the variable to contain the data, and the other is the functions that support the needed operations.
Here is a way to initialize an empty stack (which stores elements with " double " type):
Figure 1: Illustration of stack initialization
The way to push an element(for example, 4.5) to the stack is:
stack[top++]=4.5;
Explanation: 4.5 is the variable that we want to push into the stack. since stack[top] isn't occupied by any data, we can simply assign 4.5 to stack[top] . Then we need to make top=top+1 because now there's one more element in the stack. We can put these two sentences together, and that's stack[top++]=4.5; (note: the index of array in C begins from 0).
The way to pop an element from the stack is:
element=stack[--top];//suppose variable "element" has already been declared
Figure 3: Illustration of operation pop
4.2 Reverse Polish Expression
The expression "1+4" is a so-called "Infix expression", which means the operator "+" is in the middle of two corresponding operands. This kind of expression is not friendly to computers because of the operator's priority issues. For example, in the infix expression "1+(1+4)*(5+7)", as a human being, you know how to calculate it in the correct order, but you have no idea how to write a program to make the computer know the right order.
A "Postfix expression", however, makes the computer's life easier. It means to put two operands at the beginning and put the operator at the end of the two operands. In this way, you'll find it easier to calculate its value. For example, the Reverse Polish Expression of the expression "1+4" is "1, 4, +". For the expression "(1+4)*(5+7)", the Reverse Polish Expression is "1, 4, +, 5, 7, +, *".
You are suggested to do some practice to help you understand the human way to change infix expression into postfix expression.
4.3 Turn Infix expression to Reverse Polish expression
Follow the rules for an infix expression, and what you print is the reverse polish expression. You need a stack(initially it's empty) to help you.
c. If the incoming symbol is a left parenthesis, push it on the stack.step
Please notice that "print" here means store something for further use because our journey doesn't end here. We need the reverse polish expression to calculate the value.
Let's see an example for "(1+4)*(5+7)" step by step:
step
|
remain |
stack |
print |
comment |
0 |
(1+4)*(5+7) |
|
|
|
1 |
1+4)*(5+7) |
( |
|
|
2 |
+4)*(5+7) |
( |
1 |
|
3 |
4)*(5+7) |
(, + |
1 |
Rule b |
4 |
)*(5+7) |
(, + |
1, 4 |
|
5 |
*(5+7) |
|
1, 4, + |
Rule d |
6 |
(5+7) |
* |
1, 4, + |
Rule b |
7 |
5+7) |
*, ( |
1, 4, + |
|
8 |
+7) |
*, ( |
1, 4, +, 5 |
|
9 |
7) |
*, (, + |
1, 4, +, 5 |
10 |
10 |
) |
*, (, + |
1, 4, +, 5, 7 |
|
11 |
|
|
1, 4, +, 5, 7, +, * |
Rule d |
4.4 Calculate the Reverse Polish Expression
The final step is to calculate the expression and get the result. This is not hard.
We can still use a stack and follow these 2 rules:
At the end of the reverse polish expression, only one element remains in the stack. This is exactly the result.
Take " 1, 4, +, 5, 7, +, * " as an example:
step |
remain
|
stack
|
calculation |
0
|
1, 4, +, 5, 7, +, * |
|
|
1
|
4, +, 5, 7, +, *
|
1 |
|
2
|
+, 5, 7, +, *
|
1, 4
|
1 + 4 |
3
|
5, 7, +, *
|
5 |
|
4
|
7, +, *
|
5, 5 |
|
5
|
+, *
|
5, 5, 7
|
5 + 7
|
6
|
*
|
5, 12
|
5 * 12 |
7
|
|
60 |
|
5. General tips
5.1. How to store the Reverse Polish Expression
So, how could we store operators like '+'? One way is to store its ASCII, for '+', its ASCII is 43. However, it will confuse it with the number 43. But you can use an auxiliary array to mark out whether the element represents a number or an operator's ASCII.
int helper[120]={1,1,2,1,1,2,2};//0 means not occupied, 1 means double, 2 means char
When printing the reverse polish expression into array RVP in 4.3, you also need to update the corresponding place at the helper array, to 1(if it's an operand) or 2(if it's an operator)
Then when you need to operate on one of the elements in the array RVP, for example, RVP[5], you also need to check helper[5] to determine if it's an operator or an operand.
5.2. How to store the variables
5.3 More to explore
To test whether you know how to turn an infix expression into a postfix expression: https://www.mathblog.dk/tools/infix-postfix-converter/
https://beltoforion.de/en/muparsersse/implementation.php (a little bit different from ours, but has a similar idea)
6. Rubrics
7. Reminders
You're highly recommended to write some string-related functions and functions to support stack to help you, for example, insert a string into another string, because you may perform these operations a lot. In this way, your codes can be shorter.Chances are that you will make a lot of mistakes in this lab. So, you need to know how to debug. You shouldn't write all your codes and run all of them afterward. In this case, you'll find your codes not workingand you don't know what's the mistake. Instead, you should debug module-by-module. For example, when you finish the part of transforming reverse polish expressions, you can output them to the screen and see if they meet your expectations. Then you can go on to work on the next part.
Finally, I have to emphasize again that DO NOT ever try to break the Honor Code policy. Avoid high-risk behaviors such as sending your codes to others, publishing your codes on the Internet, submitting other students' codes, etc. We will use an AI-based program to check your codes and anyone who breaks HC willbe found out.