0

To preface this, I'm a beginner who's attempting to create a calculator in Javascript. I currently have a switch statement containing math operators. My issue is that in the switch statement, I want to include an error message (string) where division is concerned when trying to divide by 0; however, no matter what I do, I always get infinity up in the calculator's 'display.'

Any amount of help is greatly appreciated, even if it means me having to re-do this whole thing. Here is a snippet of the function(s) doing the actual calculation (though it is in a class, I will edit in the whole block of code if requested).

selectedOperation(operation) {
        if (this.currentDisplay === '') return;
        if (this.prevDisplay !== '') {
            this.calculate();
        }
        this.operation = operation;
        this.prevDisplay = this.currentDisplay;
        this.currentDisplay = '';
}

calculate() {
        let calculation;
        const previousNum = parseFloat(this.prevDisplay);
        const currentNum = parseFloat(this.currentDisplay);
        if (isNaN(previousNum) || isNaN(currentNum)) return;
        
        switch (this.operation) {
            case '+' : 
            calculation = previousNum + currentNum
            break;
        case '-' : 
            calculation = previousNum - currentNum
            break;
        case 'x' : 
            calculation = previousNum * currentNum
            break;
        case '÷' : 
            calculation = previousNum / currentNum
            if (currentNum === 0) return "error";
            break;
        default:
            return;
        }

        this.currentDisplay = calculation;
        this.operation = undefined;
        this.prevDisplay = '';
}

**EDIT**:

getDisplayNumber(number) {
        const stringNumber = number.toString();
        const integerDigits = parseFloat(stringNumber.split('.')[0]);
        const decimalDigits = stringNumber.split('.')[1];
        let integerDisplay
        if (isNaN(integerDigits)) {
            integerDisplay = '';
        } else {
            integerDisplay = integerDigits.toLocaleString('en', {maximumFractionDigits: 0 });
        }
        if (decimalDigits != null) {
            return `${integerDisplay}.${decimalDigits}`;
        } return integerDisplay;
    }

updateDisplay() {
        this.cdisplay.innerText = 
        this.getDisplayNumber(this.currentDisplay);
        if(this.operation != null) {
            this.display.innerText = 
                `${this.prevDisplay} ${this.operation}`;

        } else {
            this.display.innerText = '';
        }
    }
TM2020
  • 17
  • 4
  • You should consider validating `currentNum` before attempting the operation. Perhaps this previous answer will help: https://stackoverflow.com/questions/8072323/best-way-to-prevent-handle-divide-by-0-in-javascript – brew Jul 08 '20 at 08:13
  • it doesn't seem like you are capturing the return, rather, just calling `calculate()` in `selectedOperation()`. store returned value in a variable and check it(?). – iAmOren Jul 08 '20 at 09:17

1 Answers1

0

Here is the updated solution. Check the explanation in the comments.

BTW the first argument passed to addEvenListener callback is an event, not the button itself but you can access the button using event.target.

class Calculator {
  constructor(display, cdisplay) {
    this.display = display;
    this.cdisplay = cdisplay;
    this.clear();
  }

  clear() {
    this.currentDisplay = "";
    this.prevDisplay = "";
    // new property error
    this.error = "";
    this.operation = undefined;
  }

  del() {
    this.currentDisplay = this.currentDisplay.toString().slice(0, -1);
  }

  appendNumber(number) {
    // if an error exists and the user try to start a new operation
    // clear everything
    if (this.error) {
      this.clear();
    }
    if (number === "." && this.currentDisplay.includes(".")) return;
    this.currentDisplay = this.currentDisplay.toString() + number.toString();
  }

  selectedOperation(operation) {
    if (this.currentDisplay === "") return;
    if (this.prevDisplay !== "") {
      this.calculate();
    }
    this.operation = operation;
    this.prevDisplay = this.currentDisplay;
    this.currentDisplay = "";
  }

  calculate() {
    let calculation;
    const previousNum = parseFloat(this.prevDisplay);
    const currentNum = parseFloat(this.currentDisplay);
    if (isNaN(previousNum) || isNaN(currentNum)) return;

    switch (this.operation) {
      case "+":
        calculation = previousNum + currentNum;
        break;
      case "-":
        calculation = previousNum - currentNum;
        break;
      case "x":
        calculation = previousNum * currentNum;
        break;
      case "÷":
        // if the user divide by 0 set this.error
        if (currentNum === 0) this.error = "Can't divide by zero";
        // else calculate normally
        else calculation = previousNum / currentNum;
        break;
      default:
        return;
    }

    this.currentDisplay = calculation;
    this.operation = undefined;
    this.prevDisplay = "";
  }

  getDisplayNumber(number) {
    const stringNumber = number.toString();
    const integerDigits = parseFloat(stringNumber.split(".")[0]);
    const decimalDigits = stringNumber.split(".")[1];
    let integerDisplay;
    if (isNaN(integerDigits)) {
      integerDisplay = "";
    } else {
      integerDisplay = integerDigits.toLocaleString("en", {
        maximumFractionDigits: 0
      });
    }
    if (decimalDigits != null) {
      return `${integerDisplay}.${decimalDigits}`;
    }
    return integerDisplay;
  }

  updateDisplay() {
    // if there is an error display the error and return
    if (this.error) {
      this.display.innerText = this.error;
      return;
    }
    this.cdisplay.innerText = this.getDisplayNumber(this.currentDisplay);
    if (this.operation != null) {
      this.display.innerText = `${this.prevDisplay} ${this.operation}`;
    } else {
      this.display.innerText = "";
    }
  }
}

const cdisplay = document.querySelector("#cdisplay");
const display = document.querySelector("#display");
const numberButtons = document.querySelectorAll(".numbers");
const operationButtons = document.querySelectorAll(".operation");
const equalsButton = document.querySelector("#equals");
const delButton = document.querySelector("#del");
const clearButton = document.querySelector("#clear");
const negButton = document.querySelector("#neg");

const calculator = new Calculator(display, cdisplay);

numberButtons.forEach(button => {
  button.addEventListener("click", () => {
    calculator.appendNumber(button.innerText);
    calculator.updateDisplay();
  });
});

operationButtons.forEach(button => {
  button.addEventListener("click", () => {
    calculator.selectedOperation(button.innerText);
    calculator.updateDisplay();
  });
});

// this agrument passed to the callback function is an event not button
equalsButton.addEventListener("click", event => {
  calculator.calculate();
  calculator.updateDisplay();
});
// this agrument passed to the callback function is an event not button
clearButton.addEventListener("click", event => {
  calculator.clear();
  calculator.updateDisplay();
});
// this agrument passed to the callback function is an event not button
delButton.addEventListener("click", event => {
  calculator.del();
  calculator.updateDisplay();
});
Ahmed Mokhtar
  • 2,388
  • 1
  • 9
  • 19
  • 1
    Thank you for the help! I really appreciate it, the solution you gave does provide an error message; however, there seems to be a weird interaction going on with the display function. The error message only shows up after I choose another operator. On the calculator "screen", it would then display: "Can't divide by zero +" for example if I chose '+', it does the same for all of the other operators as well. I've added the display function above if you'd like to see it. – TM2020 Jul 09 '20 at 04:59
  • Can you post all your code or share it in Codepen or something so that I can help you better. – Ahmed Mokhtar Jul 09 '20 at 05:49
  • 1
    Yes of course, here's the link: https://codepen.io/superboy20/pen/eYJrVLN – TM2020 Jul 09 '20 at 07:37