I created a basic calculator in JavaScript which takes the value of the innerHTML and performs the calculations, and it sort of works, except that it doesn't chain multiple operations i.e 1 + 2 returns 3, but 1 + 2 + 1 also returns 3. Please can anyone help with this thanks.
/
My HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Calculator</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<h1 id="field">myCalculator</h1>
<table>
<tr>
<td id="main" colspan="4">
<div id="display1"></div>
</td>
</tr>
<tr>
<td class="numbers"><button id="power">^</button></td>
<td class="numbers"><button id="squareroot">√</button></td>
<td class="numbers"><button id="delete">DEL</button></td>
<td class="numbers"><button id="clear">C</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>0</button></td>
<td class="numbers"><button class='btn-input'>1</button></td>
<td class="numbers"><button class='btn-input'>2</button></td>
<td class="numbers"><button id="divide">/</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>3</button></td>
<td class="numbers"><button class='btn-input'>4</button></td>
<td class="numbers"><button class='btn-input'>5</button></td>
<td class="numbers"><button id="multiply">*</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>6</button></td>
<td class="numbers"><button class='btn-input'>7</button></td>
<td class="numbers"><button class='btn-input'>8</button></td>
<td class="numbers"><button id="subtract">-</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>9</button></td>
<td class="numbers"><button id="dot">.</button></td>
<td class="numbers"><button id="add">+</button></td>
<td class="numbers"><button id="equals">=</button></td>
</tr>
</table>
<script src="main.js"></script>
</body>
</html>
And JavaScript:
"use strict";
let display = document.getElementById("display1");
function operatorButton() {
var button = document.getElementById("squareroot");
button.addEventListener("click", function () {
display.innerHTML += "√";
})
var button = document.getElementById("power");
button.addEventListener("click", function () {
display.innerHTML += "^";
})
var button = document.getElementById("divide");
button.addEventListener("click", function () {
display.innerHTML += "/";
})
var button = document.getElementById("multiply");
button.addEventListener("click", function () {
display.innerHTML += "*";
})
var button = document.getElementById("subtract");
button.addEventListener("click", function () {
display.innerHTML += "-";
})
var button = document.getElementById("add");
button.addEventListener("click", function () {
display.innerHTML += "+";
})
var button = document.getElementById("dot");
button.addEventListener("click", function () {
display.innerHTML += ".";
})
var button = document.getElementById("clear");
button.addEventListener("click", function () {
display.innerHTML = "";
})
var button = document.getElementById("delete");
button.addEventListener("click", function () {
display.innerHTML = display.innerHTML.slice(0, display.innerHTML.length - 1);
})
}
operatorButton();
function numButton() {
let button = document.querySelectorAll('.btn-input');
for (let i = 0; i < button.length; i++) {
button[i].addEventListener("click", function () {
display.innerHTML += i
})
}
}
numButton();
const addition = (operand1, operand2) => operand1 + operand2;
const subtraction = (operand1, operand2) => operand1 - operand2;
const multiplication = (operand1, operand2) => operand1 * operand2;
const division = (operand1, operand2) => operand1 / operand2;
const squareroot = (operand1) => Math.sqrt(operand1);
const power = (operand1, operand2) => Math.pow(operand1, operand2);
function operate(operand1, operator, operand2) {
switch (operator) {
case '^':
return power(operand1, operand2);
case '/':
return division(operand1, operand2);
case '*':
return multiplication(operand1, operand2);
case '+':
return addition(operand1, operand2);
case '-':
return subtraction(operand1, operand2);
default:
break;
}
}
operate();
function operate1(operator, operand1) {
switch (operator) {
case '√':
return squareroot(operand1);
default:
break;
}
}
operate1();
function calculator() {
var button = document.getElementById("equals");
button.addEventListener("click", function () {
let calculation = display.innerHTML.split('');
let operation, answer, operand1, operand2;
for (let i = 0; i < calculation.length; i++) {
if (calculation[i] === "^" || calculation[i] === "/" || calculation[i] === '*' || calculation[i] === "+" || calculation[i] === "-") {
let operationPos = calculation.indexOf(calculation[i]);
operation = calculation[i];
operand1 = parseFloat(calculation.slice(0, operationPos).join(''));
operand2 = parseFloat(calculation.slice(operationPos + 1).join(''));
answer = operate(operand1, operation, operand2);
display.innerHTML = (answer);
} else if (calculation[i] === "√") {
let operationPos = calculation.indexOf(calculation[i]);
operation = calculation[i];
operand1 = parseFloat(calculation.slice(operationPos + 1).join(''));
answer = operate1(operation, operand1);
display.innerHTML = (answer);
}
}
})
}
calculator();
I created a basic calculator in JavaScript which takes the value of the innerHTML and performs the calculations, and it sort of works, except that it doesn't chain multiple operations i.e 1 + 2 returns 3, but 1 + 2 + 1 also returns 3. Please can anyone help with this thanks.
https://jsfiddle/d2x6e7aj/
My HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Calculator</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<h1 id="field">myCalculator</h1>
<table>
<tr>
<td id="main" colspan="4">
<div id="display1"></div>
</td>
</tr>
<tr>
<td class="numbers"><button id="power">^</button></td>
<td class="numbers"><button id="squareroot">√</button></td>
<td class="numbers"><button id="delete">DEL</button></td>
<td class="numbers"><button id="clear">C</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>0</button></td>
<td class="numbers"><button class='btn-input'>1</button></td>
<td class="numbers"><button class='btn-input'>2</button></td>
<td class="numbers"><button id="divide">/</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>3</button></td>
<td class="numbers"><button class='btn-input'>4</button></td>
<td class="numbers"><button class='btn-input'>5</button></td>
<td class="numbers"><button id="multiply">*</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>6</button></td>
<td class="numbers"><button class='btn-input'>7</button></td>
<td class="numbers"><button class='btn-input'>8</button></td>
<td class="numbers"><button id="subtract">-</button></td>
</tr>
<tr>
<td class="numbers"><button class='btn-input'>9</button></td>
<td class="numbers"><button id="dot">.</button></td>
<td class="numbers"><button id="add">+</button></td>
<td class="numbers"><button id="equals">=</button></td>
</tr>
</table>
<script src="main.js"></script>
</body>
</html>
And JavaScript:
"use strict";
let display = document.getElementById("display1");
function operatorButton() {
var button = document.getElementById("squareroot");
button.addEventListener("click", function () {
display.innerHTML += "√";
})
var button = document.getElementById("power");
button.addEventListener("click", function () {
display.innerHTML += "^";
})
var button = document.getElementById("divide");
button.addEventListener("click", function () {
display.innerHTML += "/";
})
var button = document.getElementById("multiply");
button.addEventListener("click", function () {
display.innerHTML += "*";
})
var button = document.getElementById("subtract");
button.addEventListener("click", function () {
display.innerHTML += "-";
})
var button = document.getElementById("add");
button.addEventListener("click", function () {
display.innerHTML += "+";
})
var button = document.getElementById("dot");
button.addEventListener("click", function () {
display.innerHTML += ".";
})
var button = document.getElementById("clear");
button.addEventListener("click", function () {
display.innerHTML = "";
})
var button = document.getElementById("delete");
button.addEventListener("click", function () {
display.innerHTML = display.innerHTML.slice(0, display.innerHTML.length - 1);
})
}
operatorButton();
function numButton() {
let button = document.querySelectorAll('.btn-input');
for (let i = 0; i < button.length; i++) {
button[i].addEventListener("click", function () {
display.innerHTML += i
})
}
}
numButton();
const addition = (operand1, operand2) => operand1 + operand2;
const subtraction = (operand1, operand2) => operand1 - operand2;
const multiplication = (operand1, operand2) => operand1 * operand2;
const division = (operand1, operand2) => operand1 / operand2;
const squareroot = (operand1) => Math.sqrt(operand1);
const power = (operand1, operand2) => Math.pow(operand1, operand2);
function operate(operand1, operator, operand2) {
switch (operator) {
case '^':
return power(operand1, operand2);
case '/':
return division(operand1, operand2);
case '*':
return multiplication(operand1, operand2);
case '+':
return addition(operand1, operand2);
case '-':
return subtraction(operand1, operand2);
default:
break;
}
}
operate();
function operate1(operator, operand1) {
switch (operator) {
case '√':
return squareroot(operand1);
default:
break;
}
}
operate1();
function calculator() {
var button = document.getElementById("equals");
button.addEventListener("click", function () {
let calculation = display.innerHTML.split('');
let operation, answer, operand1, operand2;
for (let i = 0; i < calculation.length; i++) {
if (calculation[i] === "^" || calculation[i] === "/" || calculation[i] === '*' || calculation[i] === "+" || calculation[i] === "-") {
let operationPos = calculation.indexOf(calculation[i]);
operation = calculation[i];
operand1 = parseFloat(calculation.slice(0, operationPos).join(''));
operand2 = parseFloat(calculation.slice(operationPos + 1).join(''));
answer = operate(operand1, operation, operand2);
display.innerHTML = (answer);
} else if (calculation[i] === "√") {
let operationPos = calculation.indexOf(calculation[i]);
operation = calculation[i];
operand1 = parseFloat(calculation.slice(operationPos + 1).join(''));
answer = operate1(operation, operand1);
display.innerHTML = (answer);
}
}
})
}
calculator();
Share
Improve this question
edited Jul 3, 2020 at 9:36
viam0Zah
26.3k8 gold badges79 silver badges103 bronze badges
asked Jul 3, 2020 at 9:15
aasonuaasonu
954 silver badges11 bronze badges
3
- Want to know the proper way to do that? You can study it here: flatassembler.github.io/piler.html Or, if robustness isn't too important to you, look here: flatassembler.github.io/calculator.html – FlatAssembler Commented Jul 3, 2020 at 9:19
- I see you wrote functions only to call them once (the ones with the event listener) - why not set them up without the functions? – iAmOren Commented Jul 3, 2020 at 10:52
-
to parse the calculator string you'd need to acmodate for operator precedence - like suggested in some of the answers - that means stacks, pushes, pops. You could use
eval
, but I like how your logic. if you do useeval
you'd need to addMath.sqrt
andMath.pow
(and closing parentheses) around them in the calculator's value to be evaluated... – iAmOren Commented Jul 3, 2020 at 10:56
5 Answers
Reset to default 3If passing this string "1+2*3". The calculation result is wrong
var str = "124-2+3*10";
var calculation = str.match(/\d+|[^0-9]/g);
var result;
for (var a = 0; a < calculation.length; a++) {
if (a == 0) {
result = parseInt(calculation[a]);
} else {
if (!isNaN(calculation[a])) {
switch (calculation[a - 1]) {
case "-":
result -= parseInt(calculation[a]);
break;
case "+":
result += parseInt(calculation[a]);
break;
case "*":
result *= parseInt(calculation[a]);
break;
case "/":
result /= parseInt(calculation[a]);
break;
}
}
}
}
console.log(result);
Let's say we enter a calculation like 1+2+2 into your calculator and hit the equal button. Inside the equal buttons click event handler it turns this string into a string array of single characters:
["1","+","2","+","2"]
because of this line:
let calculation = display.innerHTML.split('');
Now this is great if you really ever want to just calculate single-digit numbers but will fail if it has more.
e.g. 12+2+2 would turn into ["1","2","+","2","+","2"]
There is a more elegant way to separate the operators from the numbers by using a regular expression.
So let's take a look at another example - let's use the following calculation:
var str = "124-2+3*10";
and feed this string into this regular expression:
var calculation = str.match(/\d+|[^0-9]/g);
now the returned array will look a little like this:
[ "124", "-", "2", "+", "3", "*", "10" ]
The \d+
operator matches any number, while [^0-9]
matches anything that ain't a number.
If we want to include decimal numbers the above would fail though since the dot would be treated as not being a number and thus splitting a decimal number in two.
To take care of that we can enhance the regular expression to include decimal numbers like:
var calculation = str.match(/\d+\.\d+|\d+|[^0-9]/g);
Now it's just a matter of looping over the returned array, find out if the current element is an operator and do the math, so to speak.
Finding out if it's a number or an operator is done using the isNan(input)
function, which first tries to convert the input to a number and in case it fails to do so returns false.
Here's an example:
var str = "124-2+3*10";
var calculation = str.match(/\d+|[^0-9]/g);
var result;
for (var a = 0; a < calculation.length; a++) {
if (a == 0) {
result = parseInt(calculation[a]);
} else {
if (!isNaN(calculation[a])) {
switch (calculation[a - 1]) {
case "-":
result -= parseInt(calculation[a]);
break;
case "+":
result += parseInt(calculation[a]);
break;
case "*":
result *= parseInt(calculation[a]);
break;
case "/":
result /= parseInt(calculation[a]);
break;
}
}
}
}
console.log(result);
Please note: This isn't the way calculators normally work. Also this solution doesn't take care of negative numbers. It's just something to get you started.
In your function calculator()
you're looping over the elements with for (let i = 0; i < calculation.length; i++) {
. What's missing here is storing the intermediate result and using it as operand1 when puted.
You can have an array of operators (+, - ... etc), and split the input string by operators, that will create you an array with numbers which are going to be calculated, then just try to find out an algorithm how to calculate using the operation priorities ('(', /, *, +, -, etc.)
when more than 2 values I suggest to put numbers into array and cumulate it with reduce()
I mean sum, multiply, divide etc
because you have only two operands you must cumulate the value
generally 1+2+1
1*2*1
1/2/1
I mean you must have accumulator to operate on next values
or make use of closure with intermediate result
but with reduce() I see shorting because it works with one operator at time for example only sum the values
I assume you want to bine the operators like 1+2*1
so use of closure should be ok