Working on a Calculator function. Everything works as it should with one exception.
Any single operation or string of operations with a negative number results in NaN instead of the correct answer.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Calculator II</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<div class="display"><output id="output">Display</output></div>
<div id="buttons">
<div id="row1">
<button class="oper" id="+">+</button><button class="oper" id="-">-</button><button class="oper" id="*">*</button>
</div>
<div id="row2">
<button class="oper" id="/">/</button><button class="alt" id="back"><-</button><button class="alt" id="clear">C</button>
</div>
<div id="row3">
<button class="nbr" id="1">1</button><button class="nbr" id="2">2</button><button class="nbr" id="3">3</button>
</div>
<div id="row4">
<button class="nbr" id="4">4</button><button class="nbr" id="5">5</button><button class="nbr" id="6">6</button>
</div>
<div id="row5">
<button class="nbr" id="7">7</button><button class="nbr" id="8">8</button><button class="nbr" id="9">9</button>
</div>
<div id="row6">
<button class="nbr" id="0">0</button><button id="decimal">.</button><button class="alt" id="equals">=</button>
</div>
</div>
</body>
</html>
JS
let display = "0";
let result = 0;
let num1 = "";
let operand = "";
let num2 = "";
let outputElement = document.getElementById("output");
//basic math functions
function add(num1, num2) {
result = display = num1 + num2; // combining result and display to a single line.
console.log("add", result, "d", display);
return result;
}
function subtract(num1, num2) {
result = display = num1 - num2;
console.log("sub", result, "d", display);
return result;
}
function multiply(num1, num2) {
result = display = num1 * num2;
console.log("mult", result, "d", display);
return result;
}
function divide(num1, num2) {
result =
num2 === 0
? (console.log("divide by zero? Hoser!"),
alert("cannot divide by zero"),
0)
: (display = num1 / num2);
}
function clear() {
result = 0;
display = "0";
num1 = "";
operand = "";
num2 = "";
console.log("clear", num1, operand, num2, "d", display);
}
function performCalculation(){
switch (operand) {
case "+":
console.log(operand);
add(parseFloat(num1), parseFloat(num2));
break;
case "-":
console.log(operand);
subtract(parseFloat(num1), parseFloat(num2));
break;
case "*":
console.log(operand);
multiply(parseFloat(num1), parseFloat(num2));
break;
case "/":
console.log(operand);
divide(parseFloat(num1), parseFloat(num2));
break;
default:
console.log("switch", "Houston we have a problem!");
}
}
function equals() {
console.log("equals");
const calculationString = display.replace(/[^0-9+-*/.]/g, "");
console.log('cs', calculationString);
const calculations = calculationString.split(/([-+*/])/);
console.log('c', calculations);
result = parseFloat(calculations[0]);
display = result.toString();
for (let i = 1; i < calculations.length; i += 2) {
operand = calculations[i];
num1 = display;
num2 = calculations[i + 1];
performCalculation();
display = result.toString();
}
outputElement.textContext = display;
}
let buttons = document.getElementById("buttons");
buttons.addEventListener("click", clickHandler);
function clickHandler(e) {
if (display === "0") {
display = "";
}
let clicked = e.target;
if (clicked.classList.contains("nbr")) {
let number = clicked.id;
// if (display === "0") {
// display = "";
// }
if (operand === "") {
if (!num1.includes(".") || num1.split(".")[1].length < 3) {
display += number;
num1 += number;
}
} else {
if (!num2.includes(".") || num2.split(".")[1].length < 3) {
display += number;
num2 += number;
}
}
} else if (clicked.classList.contains("oper")) {
display += clicked.id;
if (clicked.id === "-" && operand === "") {
if (num1 === "") {
num1 += "-";
} else {
num2 += "-";
}
} else {
operand = clicked.id;
console.log("CH Oper", operand);
}
} else if (clicked.id === "equals") {
console.log("=");
equals();
display = parseFloat(display).toFixed(3).toString();
display = display.replace(/.?0*$/, "");
} else if (clicked.id === "clear") {
clear();
} else if (clicked.id === "back") {
display = display.slice(0, -1);
if (operand === "") {
num1 = num1.slice(0, -1);
} else {
num2 = num2.slice(0, -1);
}
} else if (clicked.id === "decimal") {
display += ".";
if (operand === "") {
if (!num1.includes(".")) {
num1 += ".";
}
} else {
if (!num2.includes(".")) {
num2 += ".";
}
}
}
console.log("clicked", clicked, "d", display);
console.log(num1, operand, num2, "d", display);
outputElement.textContent = display;
}
I believe the problem is with ‘calculation’ reading the array that is separating in nums and operands.
I have tried a variety of tweaks to calculationString. The following was tried from the bottom up:
const calculationString = display.replace(/[^0-9+-*/.]/g, "");
const calculations = calculationString.split(/([+-*/])/).filter(Boolean);
const calculations = calculationString.split(/([-+*/])/).filter(Boolean);
const calculations = calculationString.split(/(?<!d)-|+|*|//);
const calculations = calculationString.split(/([-+*/])s*/);
const calculations = calculationString.split(/(-?[-+*/])/);
I believe those are called regular expressions and I really do not understand them very well.
This is the last hurdle for me to wrap up this project short of CSS beautification. Help is much appreciated.
2
Answers
It’s a complicated process to calculate an operation based on a string input, you can check some of the answers from here. Now a quick fix for your calculator is separating * and / first then doing + and -.
(Note: this doesn’t work for bigger numbers since I’m doing the
calculation.length > 2
, there’s a lot of checks to do there if it starts with a "-" and doesn’t have another addition or subtraction afterwards)Then add a fix for the first number just in case
You can expand your calculator here:
The reason is that you are trying to do a calculation with an empty string. My fix makes it so that if the value in the array is an empty string it is replaced with 0
In function
equals()
I made this changeExample: -5-10