JS Calculator Errors

JS Calculator Errors
0

#1

I’ve been trying many things to figure out how to solve the two problems I’ve encountered.

The problems are:

  1. When trying to input “0”, subMath shows 00 - 6
  2. Equation doesn’t work properly. For example, I entered 1 + 2 and then press “=”, showing 3, but when I try to click on “+” afterward, it add 3 to the subMath, showing 1 + 23. Therefore, after “=” sign, mainMath should be equal to the final answer.

My codepen is: https://codepen.io/kikibres/pen/MEQvqv.

I did several solutions but I couldn’t find the right solution that’ll solve both problems…

My Javascript code is:

$(document).ready(function() {
  
  var mainMath = "0";
  var subMath = "0";
  var finalset = "";
  var nextanswer = "";
  update();
  
  $("button").click(function(){
    calculate($(this).attr("value"));
  });
  
  function calculate(keyitem) {
    switch(keyitem) {
      case "clear":
        clearScreen();
        break;
      case "plusminus":
        plusminusScreen();
        break;
      case "%":
        percentageScreen();
        break;
      case "/":
      case "*":
      case "+":
      case "-":
        addOperator(keyitem);
        break;
      case "0":
      case "1":
      case "2":
      case "3":
      case "4":
      case "5":
      case "6":
      case "7":
      case "8":
      case "9":
        addNumber(keyitem);
        break;
      case ".":
        addDecimal(keyitem);
        break;
      case "=":
        solveEqual();
        break;
    }
    update();
    };
 
  function clearScreen() {
     mainMath = "0";
     subMath = "0";
    if(mainMath.length > 0){
      $(".entry").css("font-size", "4em");
    }
  };
  
  function plusminusScreen() {
     mainMath = -1 * mainMath;
    finalset = mainMath;
  };
  
  function addNumber(keyitem) {
    if (mainMath == "0"){
      mainMath = keyitem;
      finalset = mainMath;
      return;
    } 
    mainMath+=keyitem;
      /*subMath += "";*/
    if(mainMath.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    
  };
  
  function addOperator(keyitem){
    if(mainMath == "0"){
    subMath += "0";
    }
    if(subMath == "0"){
      subMath = "";
    }
    /*subMath += "";*/
    addNumber(keyitem);
    subMath += mainMath;
    mainMath = "0";
  };
  
  function addDecimal(keyitem){
    /*if (keyitem == "."){*/
    if (mainMath.indexOf(keyitem) === -1){
      if(mainMath == "0") {
        mainMath = "0" + keyitem;
        subMath = "0";
        return;
      }
    } else {
        return;
      }
    /*}*/
    addNumber(keyitem);
  };
  
  function solveEqual() {
    mainMath = eval(subMath+mainMath);
    subMath += finalset;
    var finalresult = mainMath.toString();
    if(finalresult.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
  };
  
  function update(){
  $("#answer").html(mainMath);
  $("#history").html(subMath);
};
  
});

#2

If I enter 7 + 3 = then + 5, I get 322, because in your addOperator function you have:

addNumber(keyitem);
subMath += mainMath;

After click 7 +, the addNumber function makes mainMath equal “7+” and hence subMath is “7+” because before the the 2nd line above, subMatch was “”. Once the “=” button is clicked, mainMath is 10. Then, when I hit the + button, the addNumber function makes mainMath “10+”. Since subMath was “7+3” before the subMath += mainMath line above, then this line makes subMath “7+310+”. Why? Because subMath (“7+3”) is a string and mainMath (“10+”) is a string and this line concatenates the two strings together to become one string of “7+310+”. Then after the 5 is clicked and the “=” button is clicked, your output is 322, because 7+310+5 is 322.


#3

I appreciate you pointing out the source of the problem and explanation. Your explanation is very interesting.

However, you didn’t provide the solution.

I did try to work things out but I was only able to solve half of it. Here’s my updated JS code:

$(document).ready(function() {
  
  var mainMath = "0";
  var subMath = "0";
  var finalset = "";
  var finalnumber = "";
  var nextsolve = "";
  var nextanswer = "";
  update();
  
  $("button").click(function(){
    calculate($(this).attr("value"));
  });
  
  function calculate(keyitem) {
    switch(keyitem) {
      case "clear":
        clearScreen();
        break;
      case "plusminus":
        plusminusScreen();
        break;
      case "%":
        percentageScreen();
        break;
      case "/":
      case "*":
      case "+":
      case "-":
        addOperator(keyitem);
        break;
      case "0":
      case "1":
      case "2":
      case "3":
      case "4":
      case "5":
      case "6":
      case "7":
      case "8":
      case "9":
        addNumber(keyitem);
        break;
      case ".":
        addDecimal(keyitem);
        break;
      case "=":
        solveEqual(keyitem);
        break;
    }
    update();
    };
 
  function clearScreen() {
     mainMath = "0";
     subMath = "0";
     nextanswer = "";
    if(mainMath.length > 0){
      $(".entry").css("font-size", "4em");
    }
  };
  
  function plusminusScreen() {
     mainMath = -1 * mainMath;
    finalset = mainMath;
  };
  
  function addNumber(keyitem) {
    if (mainMath == "0"){
      mainMath = keyitem;
      finalset = mainMath;
      finalnumber = keyitem;
      return;
    } 
    finalnumber = keyitem;
    mainMath+=keyitem;
      
    if(mainMath.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    
  };
  
  function addOperator(keyitem){
    if(mainMath == "0"){
    subMath += "0";
    }
    if(subMath == "0"){
     subMath = ""; 
    }
    if (finalnumber == "0") {
      subMath = "0";
    }
    if (nextsolve == "="){
      subMath = "";
    }
    addNumber(keyitem);
    subMath += mainMath;
    mainMath = "0";
  };
  
  function addDecimal(keyitem){
    /*if (keyitem == "."){*/
    if (mainMath.indexOf(keyitem) === -1){
      if(mainMath == "0") {
        mainMath = "0" + keyitem;
        subMath = "0";
        return;
      }
    } else {
        return;
      }
    /*}*/
    addNumber(keyitem);
  };
  
  function solveEqual(keyitem) {
    mainMath = eval(subMath+mainMath);
    subMath += finalset;
    var finalresult = mainMath.toString();
    if(finalresult.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    nextsolve = keyitem;
    nextanswer = mainMath;
  };
  
  function update(){
  $("#answer").html(mainMath);
  $("#history").html(subMath);
};
  
});

As you can see, I tried to add a new statement to addOperator();

    if (nextsolve == "="){
      subMath = "";
    }

However, it now created new problems.

  1. When pressing “0”, the history (subMath) shows “0-3”. However, after pressing “=” and the pressing “clear”, I press “0”, but it didn’t show up in the history.
  2. Multiply operations works the first time. However, after clicking “=” and then pressing “clear”, it didn’t show the full operations. For example, if I entered “1”, then “+”, it shows up in history(subMath) as “1+”, then I press “2” and “+”, it clears the history(subMath), showing instead “2+”.

#4

I did not provide a solution because I was hoping by pointing out where the problem is, you would be able to figure out a solution that best fits your overall direction with the challenge. My solution to your problem would be to rethink your approach to the challenge. You solution has many variables which are constantly being manipulated between “0”, “”, and various concatenations. You might want to step back and break the problem down into smaller pieces, because your functions seem to be be doing too many things (i.e. manipulating too many variables at a time).

Even though I think you may be complicating the solution a little, I still think your approach is possible. You need to add some console.log statements in a various points of your code, so you can see before an after versions of the variables you a manipulating. I think you will be surprised in what is happening at a couple places in your code.


#5

I used console.log for most of the statements and I pretty much got the gist of my code. However, I still cannot solve it. My new idea is to get mainMath plus operator and push it to subMath every time someone press an operator or equal. I tried to code it that way but I was unable to do so. Could you please point out what’s wrong in some areas in red marks or something like that and I’ll try to fix it?

Update:
I think I fixed half of it but I still would like for you to point out what’s wrong with some code. I’m going to take a break to clear my head and maybe get some inspiration…


#6

Console.log was great help in figuring out the code and rearranging everything… my new code is completely different from my older code. However, I couldn’t get the equation to work properly after I press “=”. I thought that if I add if equal is true in function addOperator(), then it’ll clear the array and add the final answer to the array…

Here’s my new code:

$(document).ready(function() {
  
  var mainMath = "0";
  var subMath = "0";
  var finalset = "";
  var finalnumber = "";
  var nextsolve = "";
  var nextanswer = "";
  var subMatharray = [];
  var equaltrue = false;
  update();
  
  $("button").click(function(){
    calculate($(this).attr("value"));
  });
  
  function calculate(keyitem) {
    console.log("buttonpress: " + keyitem);
    switch(keyitem) {
      case "clear":
        clearScreen();
        break;
      case "%":
        percentageScreen();
        break;
      case "/":
      case "*":
      case "+":
      case "-":
        addOperator(keyitem);
        break;
      case "plusminus":
        plusminusScreen();
        break;
      case "0":
      case "1":
      case "2":
      case "3":
      case "4":
      case "5":
      case "6":
      case "7":
      case "8":
      case "9":
        addNumber(keyitem);
        break;
      case ".":
        addDecimal(keyitem);
        break;
      case "=":
        solveEqual(keyitem);
        break;
    }
    update();
    };
 
  function clearScreen() {
     mainMath = "0";
     subMath = "0";
     subMatharray = [];
    if(mainMath.length > 0){
      $(".entry").css("font-size", "4em");
    }
    console.log("clearMain: " + mainMath);
    console.log("clearSub: " + subMath);
  };
  
  function plusminusScreen() {
     mainMath = -1 * mainMath;
    finalset = mainMath;
    console.log("plusminusMain: " + mainMath);
    console.log("plusminusFinal: " + finalset);
  };
  
  function addNumber(keyitem) {
    if (mainMath == "0"){
      mainMath = keyitem/*mainMath.replace("0", keyitem);*/
      finalset = mainMath;
      return;
      console.log("addedMainZero: " + mainMath);
      console.log("addedFinalZero: " + finalset);
    }
    finalnumber = keyitem;
    mainMath+=keyitem;
    finalset = mainMath;
    console.log("addedMain: " + mainMath);
    console.log("addedFinalset: " + finalset);
    console.log("addedarray: " + subMatharray);
    console.log("addedFinalNumber: " + finalnumber);
    
    if(mainMath.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    
  };
  
  function addOperator(keyitem){
    /*addNumber(keyitem);*/
    /*if(finalnumber == "0"){*/
    subMatharray.push(mainMath,keyitem);
    /*}*/
    subMath = subMatharray.join("");
    mainMath = "0";
    console.log("addOpSub: " + subMath);
    console.log("addOpMain: " + mainMath);
    console.log("addOpMainarray: " + subMatharray);
    console.log("equaltrueTest: " + equaltrue);
  };
  
  function addDecimal(keyitem){
    /*if (keyitem == "."){*/
    if (mainMath.indexOf(keyitem) === -1){
      if(mainMath == "0") {
        mainMath = "0" + keyitem;
        /*subMath = "0";*/
        return;
      }
    } else {
        return;
      }
    /*}*/
    addNumber(keyitem);
  };
  
  function solveEqual(keyitem) {
    mainMath = eval(subMath+mainMath);
    console.log("solveEqualresult: " + mainMath);
    /*subMath += finalset;*/
    subMatharray.push(finalset);
    subMath = subMatharray.join("");
    console.log("solveEqualhistory: " + subMath);
    console.log("solveEqualarray: " + subMatharray);
    var finalresult = mainMath.toString();
    if(finalresult.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    equaltrue = true;
    /*nextsolve = keyitem;*/
    nextanswer = mainMath;
  };
  
  function update(){
  $("#answer").html(mainMath);
  $("#history").html(subMath);
};
  
});

and this is the code in which I took out of the function addOperator() since it wasn’t working as I thought it should:

if (equaltrue == true){
      subMatharray = [];
      subMatharray.push(nextanswer);
      console.log("addOpEqualarray: " + subMatharray);
    }

Please help?


#7

I pretty much solved most of the problems. The only problems left are:
Problems

  1. I need to work on percentage button soon…
  2. fix the problem if someone click an operator more than once.

I am currently working on the #2 problem. I would appreciate it if you can help me out the the solution to #2.

Here’s my updated code:

$(document).ready(function() {
  
  var mainMath = "0";
  var subMath = "0";
  var finalset = "";
  var subMatharray = [];
  var equaltrue = false;
  update();
  
  $("button").click(function(){
    calculate($(this).attr("value"));
  });
  
  function calculate(keyitem) {
    console.log("buttonpress: " + keyitem);
    switch(keyitem) {
      case "clear":
        clearScreen();
        break;
      case "%":
        percentageScreen();
        break;
      case "/":
      case "*":
      case "+":
      case "-":
        addOperator(keyitem);
        break;
      case "plusminus":
        plusminusScreen();
        break;
      case "0":
      case "1":
      case "2":
      case "3":
      case "4":
      case "5":
      case "6":
      case "7":
      case "8":
      case "9":
        addNumber(keyitem);
        break;
      case ".":
        addDecimal(keyitem);
        break;
      case "=":
        solveEqual(keyitem);
        break;
    }
    update();
    };
 
  function clearScreen() {
     mainMath = "0";
     subMath = "0";
     subMatharray = [];
    if(mainMath.length > 0){
      $(".entry").css("font-size", "4em");
    }
    console.log("clearMain: " + mainMath);
    console.log("clearSub: " + subMath);
  };
  
  function plusminusScreen() {
     mainMath = -1 * mainMath;
    finalset = mainMath;
    console.log("plusminusMain: " + mainMath);
    console.log("plusminusFinal: " + finalset);
  };
  
  function addNumber(keyitem) {
    if (mainMath == "0"){
      mainMath = keyitem/*mainMath.replace("0", keyitem);*/
      finalset = mainMath;
      return;
      console.log("addedMainZero: " + mainMath);
      console.log("addedFinalZero: " + finalset);
    }
    mainMath+=keyitem;
    finalset = mainMath;
    if (equaltrue == true){
      mainMath = keyitem;
      subMath = "0";
      subMatharray = [];
      console.log("addNumberEqualmain: " + mainMath);
    }
    console.log("addedMain: " + mainMath);
    console.log("addedFinalset: " + finalset);
    console.log("addedarray: " + subMatharray);
    
    if(mainMath.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    
  };
  
  function addOperator(keyitem){
    if (equaltrue == true){
      subMatharray = [];
      console.log("addOpEqualarray: " + subMatharray);
    }
    subMatharray.push(mainMath,keyitem);
    subMath = subMatharray.join("");
    mainMath = "0";
    console.log("addOpSub: " + subMath);
    console.log("addOpMain: " + mainMath);
    console.log("addOpMainarray: " + subMatharray);
    console.log("equaltrueTest: " + equaltrue);
  };
  
  function addDecimal(keyitem){
    if (mainMath.indexOf(keyitem) === -1){
      if(mainMath == "0") {
        mainMath = "0" + keyitem;
        return;
      }
    } else {
        return;
      }
    addNumber(keyitem);
  };
  
  function solveEqual(keyitem) {
    mainMath = eval(subMath+mainMath);
    console.log("solveEqualresult: " + mainMath);
    subMatharray.push(finalset);
    subMath = subMatharray.join("");
    console.log("solveEqualhistory: " + subMath);
    console.log("solveEqualarray: " + subMatharray);
    var finalresult = mainMath.toString();
    if(finalresult.length > 8){
      $(".entry").css("font-size", "1.5em");
    }
    equaltrue = true;
  };
  
  function update(){
  $("#answer").html(mainMath);
  $("#history").html(subMath);
};
  
});

#8

You have a variable called nextanswer where you assign mainMath to it at the end of the solveEqual function, but it is not used anywhere else. If I enter 7 + 5 and hit the “=” button, at the end of the solveEqual function mainMath has a value of 12. At this point, you need to add a “=12” to subMath, so it shows in the history section. However, since you are using subMath in your eval, that “=12” would cause trouble.

I suggest you separate the history section from the current calculated result by not intermixing subMath and mainMath the way you are doing. Without separating the two, your code has become very unreadable and hard to manage. The best solutions break down problems into small pieces. Treat each section as separate problems and then go back later to see if you can combine them in an efficient manner. You may need to step back and write out in plain language your algorithm for each section, so that you have a clear direction. I fear if you keep going down your current solution path, you may finish it, but it will be a series of band-aids and hacks which will result in code that is very difficult to maintain/change at a later date.


#9

I’m not sure if you’ve seen my recent post. I did try to separate the subMath from mainMath as much as possible. However, based on your recommendation, I edited the function solveEqual(). You can see the result in my Codepen link.

What I am working on right now is fixing the problem if someone click an operator more than once. My idea was to store the operators pressed in an array. If it’s more than one operator, then the array should knock off the first element and use the last element and add/replace it to the history area. Another idea was to check the length of the mainMath and operator length. If the mainMath.length is 0, meaning that there wasn’t an input after the operator is pressed and if operator.length is more than 1, then I’ll remove the last part of the subMath and add the next operator or something like that…