[JS] 계산기 만들기
1. 완성본
완성본 영상은 다음과 같다. 간단하게 사칙연산(더하기, 빼기, 곱하기, 나누기)만을 구현했다.
2. HTML 구조
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="calc-wrapper">
<form id="calc">
<div class="calc__column">
<div class="calc__display" id="calc-display">0</div>
</div>
<div class="calc__column">
<input type="button" id="num9" class="num" value="9" />
<input type="button" id="num8" class="num" value="8" />
<input type="button" id="num7" class="num" value="7" />
<input type="button" id="clear" value="C" />
</div>
<div class="calc__column">
<input type="button" id="num4" class="num" value="4" />
<input type="button" id="num5" class="num" value="5" />
<input type="button" id="num6" class="num" value="6" />
<input type="button" id="plus" value="+" />
</div>
<div class="calc__column">
<input type="button" id="num1" class="num" value="1" />
<input type="button" id="num2" class="num" value="2" />
<input type="button" id="num3" class="num" value="3" />
<input type="button" id="minus" value="-" />
</div>
<div class="calc__column">
<input type="button" id="times" value="×" />
<input type="button" id="num0" value="0" />
<input type="button" id="divide" value="÷" />
<input type="submit" id="result" value="=" />
</div>
</form>
</div>
<script src="index.js"></script>
</body>
</html>
3. CSS
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
.calc-wrapper {
width: 250px;
height: 300px;
position: relative;
margin: 0 auto;
margin-top: 50px;
background-color: #f9f9f9;
border: 1px solid #dfe1e5;
border-radius: 20px;
padding: 10px;
display: flex;
flex-direction: column;
}
.calc-wrapper form {
position: relative;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
.calc__column:first-child {
margin-bottom: 10px;
}
.calc__column:nth-child(n + 2) {
display: grid;
grid-template-columns: 55px 55px 55px 55px;
grid-gap: 2px;
margin-bottom: 10px;
padding: 1px;
}
.calc__column:last-child {
margin-bottom: 0;
}
.calc__column .calc__display {
height: 50px;
padding: 10px;
text-align: right;
font-family: Consolas;
font-size: 25px;
background-color: #ffffff;
border: 1px solid #dfe1e5;
border-radius: 5px;
}
.calc__column input {
height: 40px;
background-color: #dfe1e5;
border: none;
}
.calc__column .num {
background-color: #f1f3f4;
}
.calc__column input:focus {
outline: none;
}
.calc__column input:hover {
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.15);
}
.calc__column input:active {
border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0.52);
}
4. 자바스크립트
프로그램 코드는 크게 어렵지 않다. 계산 방식은 후위 표기법을 이용했다.
$$ 3 + 2 \times 4 $$
를 예로 들어보자.
후위 표기법이란 컴퓨터가 계산하기 쉬운 수식을 말한다. 후위 표기법을 사용하기 위해서는 스택 자료구조가 필요하다. 우리가 사용하는 위 식은 보통 중위 표기법이라고한다. 일단 이렇게만 알아두자. 이제 위 식을 컴퓨터의 계산방식을 이용해서 답을 구하는 과정을 설명하도록 하겠다.
[그림 1]을 보자. [그림 1]에는 숫자를 담는 스택과 연산자를 담는 스택이 있다. 먼저, 첫 번째 요소 3을 빼서 숫자를 담는 스택에 넣는다.
그 다음단계로 '+' 연산자를 연산자를 넣는 스택에 넣는다.
세 번째 단계 역시 2를 숫자를 넣는 스택에 넣는다.
그 다음 단계에는 곱하기 연산자를 만나게 된다. 사칙 연산 중 곱하기, 나머지 연산자는 어느 위치에 있더라도 더하기, 빼기 연산보다 먼저 계산해야한다. 그런 이유로
$$ 2 \times 4$$
를 계산하기 위해서는 다음과 같은 과정이 필요하다.
-
숫자를 넣는 스택에서 2를 꺼낸다.
-
곱하기 연산 다음 숫자 4를 배열에서 빼낸다.
-
2와 4를 곱해서 숫자를 넣는 스택에 넣는다.
마지막 단계로 연산자 스택에 있는 + 값을 꺼낸다. 꺼낸 값은 더하기 기호이므로 숫자 스택에 있는 8, 3 두 수를 더해서 숫자를 넣는 스택에 넣는다. 그러면 숫자를 넣는 스택에는 최종적으로 계산 결과 데이터만이 들어있게 된다.
따라서 프로그램 코드는 다음과 같다.
const form = document.querySelector("form");
const btn = form.querySelectorAll("input");
const display = form.querySelector("#calc-display");
let equation = [];
let num = "";
const numStack = [];
const opStack = [];
function handleDisplay(value) {
// 숫자 입력 또는 계산 결과 출력할 곳
value = value.substr(0, 14);
console.log(value);
if (!isNaN(Number(value))) {
if (num.length <= 14) {
num += value;
display.innerText = num;
}
} else {
equation.push(Number(display.innerText));
num = "";
equation.push(value);
display.innerText = "0";
}
}
function handleClear(event) {
equation = [];
num = "";
display.innerText = "0";
}
function handleInput(event) {
const value = event.target.value;
handleDisplay(value);
}
function calculate() {
//중위 표기법을 후위 표기법으로 변환
//inorderfix -> postorderfix
while (equation.length > 0) {
const item = equation.shift();
console.log("item", item);
if (!isNaN(Number(item))) {
//숫자 일때
numStack.unshift(item);
} else {
//숫자가 아닐 때
//곱하기나 나눗셈을 만났을 때!
if (item === "×") {
const num1 = numStack.shift();
const num2 = equation.shift();
numStack.unshift(num1 * num2);
} else if (item === "÷") {
const num1 = numStack.shift();
const num2 = equation.shift();
numStack.unshift(num1 / num2);
} else {
opStack.unshift(item);
}
}
}
// 계산
while (opStack.length) {
const op = opStack.shift();
const num2 = numStack.shift();
const num1 = numStack.shift();
if (op === "+") numStack.unshift(num1 + num2);
else if (op === "-") numStack.unshift(num1 - num2);
}
//출력!!
console.log("정답", numStack);
handleDisplay("" + numStack.shift());
}
function handleSubmit(event) {
event.preventDefault();
equation.push(Number(num));
num = "";
display.innerText = "";
calculate();
}
function init() {
for (let i = 0; i < btn.length - 1; i++) {
if (i === 3) btn[i].addEventListener("click", handleClear);
else btn[i].addEventListener("click", handleInput);
}
form.addEventListener("submit", handleSubmit);
}
init();