skip to Main Content

I am trying to create a calculator and unable to calculate negative numbers because my current logic splits displayValue which is a string using regular expressions(Regex) to separate numbers and operators into an array displayArray.

so, when i try to assign a negative number (lets say for example -5 – 10) i want my displayArray to take it as [‘-5’, ‘-‘, ’10’] but instead i get [”, ‘-‘, ‘5’, ‘-‘, ’10’].

so, my problem here is I know why its happening but I couldn’t figure out how to get the first array instead of the later one?

expected: [‘-5’, ‘-‘, ’10’].

Instead I get: [”, ‘-‘, ‘5’, ‘-‘, ’10’].

Here is my full code:

// Initialize variables
let displayValue = '';
let displayArray = [];

const screenDiv = document.getElementById('screen');
const numberButtons = document.querySelectorAll('.number');
const operatorButtons = document.querySelectorAll('.operator');

// Event listeners for number buttons
numberButtons.forEach(button => {
    button.addEventListener('click', () => {
        displayValue += button.textContent;
        displayArray = displayValue.split(/([+-*/])/);
        const [firstNumber, operator, secondNumber] = displayArray;

        if (displayArray.length === 3) {
            screenDiv.textContent = secondNumber;
        } else {
            screenDiv.textContent = firstNumber;
        }

        if (firstNumber === '0') {
            displayValue = '';
        }
    });
});

// Event listeners for operator buttons
operatorButtons.forEach(button => {
    button.addEventListener('click', () => {
        if (displayArray.length === 3) {
            displayValue = operate(); // Assuming operate() is a function to perform the operation
            screenDiv.textContent = displayValue;
            displayValue += button.textContent;
        } else {
            displayValue += button.textContent;
        }
    });
});

2

Answers


  1. The + or – sign can represent either a sign or an operator; therefore, a regular expression alone cannot perfectly resolve the ambiguity. Consequently, we must determine whether the character between operands functions as a sign or an operator. Below is the program flow that addresses this issue.

    First, the variable tokensQueue is designated as the resultant array.

    I extract the numbers (i.e., variable operands) from the expression using a regular expression and save all operands to the variable operands.

    Then, I extract all characters between the operands and check if each character (i.e., variable token) is a + or – sign.

    If the variable token is a + or – sign, we need to check if the last element (i.e., variable preobj) in the tokensQueue array is a number.

    If variable preobj is a number, this indicates that the variable token is a negative sign. In this case, push both token and the operand to the tokensQueue array and set flag to false.

    Otherwise, this implies that the variable token is an operator; hence, push token to the tokensQueue array.

    After checking all token characters, if flag is true, push the operand to the variable tokensQueue.

    let expression = "-5 - 10";
    //let expression = "5e-1+10" ;
    let flag = true;
    let index = -1;
    let noPattern = /d+(.d+)?(e{1}[+-]?d+)?/ig;
    
    let operands = expression.match(noPattern);
    let preObj = '';
    let startIndex = 0;
    let temp = '';
    let token, tokensQueue = [];
    operands.forEach(operand => {
      console.log('operand=' + operand + ",startIndex=" + startIndex);
      index = expression.indexOf(operand, startIndex);
      flag = true;
      for (i = startIndex; i < index; i++) {
        token = expression.substr(i, 1).trim();
        console.log("token=" + token)
        switch (token) {
          case "":
            break;
          case "+":
          case "-":
            preObj = tokensQueue[tokensQueue.length - 1];
            if (
              preObj === undefined ||  //that means the tokensQueue is empty
              preObj === "(" || //that means the `token` is a -ve sign 
              isNaN(preObj)) {  //that means the `token` is a -ve sign
              tokensQueue.push(token + operand);
              flag = false;
            } else {
              tokensQueue.push(token);
            }
            break;
        }
      }
      if (flag) {
        flag = true;
        tokensQueue.push(operand);
      }
      startIndex = index + operand.length;
    });
    console.log(tokensQueue);
    Login or Signup to reply.
  2. Based on your clarification, It seems that the issue with your string splitting is that you have to consider two cases for the - character:

    • at the beginning of the expression, you want it to be a negative signal;
    • in between numbers, you want it to be a subtraction operator.

    You can address that directly by using a String.match instead of String.split, like this:

    displayArray = displayValue.match(/((^-)?d+)|([^d]+)/g);
    

    Even though the above will give you what you asked for, I don’t think your approach will continue working for you much longer. You should consider having separate buttons for subtraction - and for changing signal (+/-), like most of the calculators you see in real life. You could even use different symbols for them, like a long dash for subtraction and a short one for negative -.

    Also, you cannot handle decimal numbers yet. You’d have to account for a possible dot in between digits.


    Besides all that, if you plan to fully implement a calculator for learning purposes, I suggest you to learn about expression trees.

    I could add a sample implementation of that by updating your code. Let me know if you need so.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search