As I mentioned in the previous post, I am, among other things, following Free Code Camp’s (FCC) curriculum. If you’re interested, you can check my solutions on my FFC account as well as on Codepen and Github account.
A couple of days ago I finished FFC’s JavaScript Calculator challenge. I spent a good amount of time on it because I did it twice. When I made the first version of my calculator, I haven’t thought about it too much before I implement it. Although it had all the basic functionality, you can also type basically any number or operator whenever you wanted (e.g. 1….5 +++ 8 =+-). However, if you take a real calculator, you will find out that it lets you use only certain numbers or operators at the certain situations. So I tried to address all these issues in the first version of my calculator but it was kind of overwhelming. Therefore, it seemed to me that it will be easier if I start all over again.
At that time, I knew that I needed to think more about the implementation of my JS calculator before I started to code. I needed to think through every possible scenario since in each phase of the arithmetical operation, you want your calculator to react only when particular keys are pressed. So I just did what you should do every time before you start to code a new project.
|
Finite State Machine |
First, I was like “No way, that sounds too difficult and it seems to me that it must be some abstract programming concept which would be hard to learn.” However, after a couple of days, I changed my mind and I started to implement the calculator using a FSM.
This post is the first from two posts where I am going to describe my implementation of the Free Code Camp’s JavaScript Calculator using a FSM. I hope that these posts will help you to build a fully functional calculator in a very effective way you’re maybe not familiar with. Also these posts will help anyone who want to program a calculator in JavaScript but struggle with it or don’t know where to start.
This post will be a little bit theoretical because we need first to think about the functionality of the FSM and how it is going to help us to build up our calculator.
Are you ready? Let’s code!
Step 1 – HTML and CSS
Before you can start to implement the calculator’s functionality, you need to design your calculator using HTML and CSS. Since we are making a calculator with the basic functionality, it should have at least these keys (of course you don't need the "info" key):
Designing your calculator is a very simple task, so I am not going to describe this part of the process.
When you have a visual version of your calculator, you need to (if you haven’t done so already) think about its functionality. When implementing a FSM, it is very useful to draw a graph of your machine first, otherwise you can get easily lost during its implementation. But before we make this graph, we need to define the states of the calculator and the variables that we are going to use to store numbers and operators.
Step 2 – Define States
If you think about calculator’s functionality (enter a number, press operator, enter a second number, press equal sign), it is obvious that it will need at least 5 basic states. You can also figure out what keys must be pressed in order to get into a certain state.
However, you need take into account the "dot" key as well. For example, if you press this key on the real calculator as a first character, your number will start with "0.". So, in the end we need to define 3 more states, that is 8 states in total.
States (you can call these states whatever you want) - the calculato transitions into a particular state when:
- START – default state of the calculator
- FIRST_ARG – a number key is pressed (as a first number)
- FIRST_ARG_FLOAT - a dot is pressed as a part of the first argument (number)
- OP – any operator is pressed (except equal sign)
- SECOND_ARG - a number key is pressed (as a second number)
- SEC_ARG_FLOAT - when a second number has a dot not at its beginning
- SEC_ARG_DOT - when a second number begins with dot (0.)
- EQUALS – when an equal sign is pressed
It is convenient and it will make your code more readable, if you store these states as the properties in an object. Each property will represent a state of your calculator. The idea is that when you refresh a page, your calculator will be in a default state and by clicking on different keys, the state is going to change. This process will go on and on, until you press a clear button on your calculator or when you refresh the page itself.
Step 3 – Define Variables
Now, you will need to define the variables. These variables are going to change a lot since they will store everything you type into your calculator. Try to keep the number of the variables as low as possible, otherwise your code might become unnecessary complicated.
Five variables should be enough:
- var state - monitors current state of the calculator
- var disp – stores the number and monitors what is currently displayed on the calculator’s display
- var acc1 - stores the first number for further operations
- var acc2 - stores the second number for further operations
- var op - monitors current arithmetical operator
In our code, these variable will be also stored in the object.
Step 4 - Graph
At this point, you have everything you need (the basic states of the calculator, which keys needs to be pressed in order to transition between these states, variables which are going to store user’s input). So, it is the right time for you to draw a graph which will put this information into the context and help you to visualize the functionality of your calculator.
When drawing this graph, you need to keep in mind that you can press only certain keys during the particular state of the calculator. For example, a real calculator won’t let you to type five dots in a row or twenty operators in a row. From every state, you can only go to the limited number of other states.
There are many ways how to draw a FSM graph and Google will help you with that.
According to the previous instructions, your basic graph should look like this:
I will describe this graph at the beginning of my second post :)
Stay Tuned!
If you like this post, or if you have any suggestions or critique, feel free to write a comment below. I would greatly appreciate it.