Final post on building a calculator.

In the last three posts, I presented a basic calculator, a quick rundown on creating the framework – or really just the graphical elements of the calculator itself, and covered some code on our number buttons. In case you missed those, you may want to catch up – with the following links.

Part 1 – The Calculator

Part 2 – The Framework

Part 3 – The Numbers

In this post, I want to conclude by working through the code for the rest of the buttons used to make the operations functional.

**The Math Functions**

Each of the four main math functions (plus, minus, times, and divide) have a similar block of code with just a couple changes between them. In the code for these four buttons you will notice some new variables coming into play.

*plus*– flag to track that the plus button was pressed*minus*– flag to track that the minus button was pressed*times*– flag to track that the times button was pressed*div*– flag to track that the divide button was pressed*pos*– flag to track that the polarity of the value

**The Code for the Math Functions**

if (window.screen==1) {

plus=1;

minus=0;

times=0;

div=0;

screen=2;

pos=1;

cp.changeState(“symbol”,”plus”);

cp.enable(“btn1”);

cp.enable(“btn2”);

cp.enable(“btn3”);

cp.enable(“btn4”);

cp.enable(“btn5”);

cp.enable(“btn6”);

cp.enable(“btn7”);

cp.enable(“btn8”);

cp.enable(“btn9”);

cp.enable(“btn0”);

cp.enable(“pctBtn”);

cp.enable(“decBtn”);

btnCount=0;

cp.hide(“currentDisplay1”);

cp.show(“currentDisplay2”);

}

Let’s take a look at what is happening. This code example is from the plus button.

First of all, we only need to verify the first display is active. This is because we are only doing one operation at a time and so the functions are not used when the second value is being entered.

Next, depending on which button is being pressed, the appropriate flag is tripped and I am making sure the others are set to zero. (This is likely one of those areas I might be able to trim the code.)

Then we change the *screen* variable to 2 which sets us up to populate the second number for our calculation.

We then set the *pos* variable to 1 in case the value from the first number was negative.

Next we have a change state for the symbol in the upper right corner of the display to show which operation is being performed. In this case, we change it to the plus symbol.

Then we have a block of code to re-enable all the number buttons in the event that all eight characters were used in the first number.

We need to reset the *btnCount* variable for use with the second display.

Finally, we need to hide the first screen and show the second one which will have a default value of zero.

All that changes between these four buttons is the variable that is tripped and the symbol that is shown.

**The Clear Button**

This button does what you might expect. It simply resets everything to their default values and then changes any states that need changing and re-enabling buttons.

d1=0;

d2=0;

ans=0;

screen=1;

plus=0;

minus=0;

times=0;

div=0;

pos=1;

btnCount=0;

cp.show(“currentDisplay1”);

cp.hide(“currentDisplay2”);

cp.hide(“currentDisplayAns”);

cp.changeState(“symbol”,”Normal”);

cp.enable(“pctBtn”);

cp.enable(“btn1”);

cp.enable(“btn2”);

cp.enable(“btn3”);

cp.enable(“btn4”);

cp.enable(“btn5”);

cp.enable(“btn6”);

cp.enable(“btn7”);

cp.enable(“btn8”);

cp.enable(“btn9”);

cp.enable(“btn0”);

cp.enable(“decBtn”);

Looking through the code, you should be able to see what is going on.

**The Plus/Minus Button**

The plus/minus button works to change the polarity of the currently displayed value.

if (window.screen==1) {

if (window.pos==1) {

d1=d1*(-1);

pos=0;

}

else if (window.pos==0) {

d1=d1*(-1)

pos=1;

}

}

if (window.screen==2) {

if (window.pos==1) {

d2=d2*(-1);

pos=0;

}

else if (window.pos==0) {

d2=d2*(-1);

pos=1;

}

}

if ((window.screen==1) && (window.d1==0)) {

pos=1;

}

if ((window.screen==2) && (window.d2==0)) {

pos=1;

}

This looks like a lot of code for this and it probably could be simplified but here is what is happening.

First we need to check which display we are updating so we have an if statement for screen 1 and screen 2 and then we do a check for the current polarity of the value. The math is the same to change the polarity which is to multiply by a negative 1, but the difference is that we need to set the polarity different. So you see pretty much the same code for both screens.

Finally, we see a similar small block of code for when the display is reading zero on either screen. In this case, we don’t change polarity and the variable does not change.

**The Percent Button**

This one does get sort of ugly in order to deal with the floating point math but here it is. Perhaps there is an easier way but this project was all about what I discovered that would work through trial and error rather than any sort of expertise.

if ((window.screen==2) && ((window.plus==1) || (window.minus==1))) {

d2=parseFloat(((d1*(d2/100))*10/10).toPrecision(8));

}

if ((window.screen==2) && ((window.times==1) || (window.div==1))){

d2=parseFloat(((d2/100)*10/10).toPrecision(8));

}

if ((window.screen==1) && (window.d1!=0)) {

d1=parseFloat(((d1/100)*10/10).toPrecision(8));

}

cp.disable(“pctBtn”);

cp.disable(“decBtn”);

cp.disable(“btn1”);

cp.disable(“btn2”);

cp.disable(“btn3”);

cp.disable(“btn4”);

cp.disable(“btn5”);

cp.disable(“btn6”);

cp.disable(“btn7”);

cp.disable(“btn8”);

cp.disable(“btn9”);

cp.disable(“btn0”);

Let’s take a closer look.

We have four blocks of code shown above. One block to cover the first number, two blocks to cover the second number, and a block to disable other buttons after using the percent button. Starting with the block for screen 1, here is what is going on.

So – if we are on screen 1 and the display reads something other than zero, we perform a calculation to convert the number to a decimal equivalent for percent. Notice that all the disabling code is outside of our if statements. They will execute regardless of which of the if statement runs. I limited its use to one time.

Converting a number to a decimal from percent is as simple as dividing by 100 but that is easier said than done with JavaScript math. You will notice that I have **d1/100** in that formula but I also do a multiplication of that by 10/10 (or 1) and I also have a ** parseFloat** and a

**in that mix. All that extra stuff is to prevent the odd occurrence of values out to like 15 decimal places. My study has shown that this is a common problem which needs to be dealt with. While there were lots of solutions offered to try and solve the issue, this one seemed to behave the best for this application. So the**

*toPrecision(8)***part allows the calculated result to go to 8 places. I stopped it there to match my display limit of 8 characters. The**

*toPrecision(8)***will strip any extra zeroes that are not needed at the end. So that a value such as 0.025000000 would only display as 0.025**

*parseFloat*For the second screen – things had to work different. So I did several tests with a real calculator to see how it would behave and found that it was different if I multiply or divide vs adding and subtracting. That is why they each have their own formula. For multiplication and division – you will notice the formula is the same as that for screen 1 but if you perform an addition or subtraction, a multiplication of the* screen1* value is performed first. Try it on your phone calculator and you will see what I mean.

**The Equals Button**

So I saved the best for last – Ha Ha. If you thought the percent button was ugly – get a load of this…

if (window.screen==2) {

if (window.plus==1) {

ans=parseFloat(((d1*10/10)+(d2*10/10)).toPrecision(8));

}

if (window.minus==1) {

ans=parseFloat((((d1*10)-(d2*10))/10).toPrecision(8));

}

if (window.times==1) {

ans=parseFloat((d1*d2).toPrecision(8));

}

if (window.div==1) {

ans=parseFloat(((d1/d2)*10/10).toPrecision(8));

}

cp.hide(“currentDisplay1”);

cp.hide(“currentDisplay2”);

cp.show(“currentDisplayAns”);

cp.changeState(“symbol”,”Normal”);

screen=3;

}

if (window.ans>99999999) {

ans=”Error”;

}

if (window.ans<-99999999) {

ans=”Error”;

}

Ok – so maybe I exaggerated a little bit. Here is what we have going on…

First of all, the equals button only fires if we are currently on screen 2. That is because if we are on screen 1 – we would only have one number and we would need two in order to perform a calculation. Then we see a formula for each of the four functions. The end result is basically d1+d2, d1-d2, d1*d2, and d1/d2 but we have to do all the other JavaScript gymnastics to get the display to show the answer nicely. The extra multiplication and division stuff also helps to convert all the strings to numbers so they can be worked with. So these four if statements will check to see which operation flag was tripped and perform the appropriate calculation.

Next we make sure the two entry displays are hidden and that our answer display is showing.

We remove the symbol for the math operation and set our *screen* variable to 3.

The final check here is that we look to see if our answer exceeds the limits of our display. If it does – we display the word “Error”.

**Conclusion**

There are still a couple bugs or issues here and there that need some tweaking but I found this to be a worthwhile project for my own growth. I plan to investigate a bit more into improving the calculator. That will involve cleaning up some code and trying to get some values stored into an array to allow a sequence of operations instead of just one at a time. Whenever that happens, I will be sure to post about it. In the meantime, maybe some of you can take away something valuable from all of this.

Yes, code is placed on each button.

When you choose the onSuccess action for the button – you’ll pick Execute JavaScript

Then you’ll find a button labeled Script Window.

You can enter your JavaScript in the resulting window.

Hope that helps.

By the way – this is a three year old project now.

I think I would probably do it a bit differently if I were to start over. I’ve learned a lot since then.

You must be logged in to post a comment.