Java 강의가 열리고 첫 번째 개인과제가 주어졌다.
바로 계산기를 만드는 것이다.
사실 코딩을 배우는 사람이라면 가장 많이 하는 것이 "Hello World!"를 찍는 것이고 두 번째로 많이 하는 것이 계산기를 만드는 것이라는 말이 있다.
이번에 배운 클래스에 대한 개념과 조건문과 반복문, 컬렉션 등을 사용하며 사칙연산을 할 수 있는 계산기를 만들어보았다.
구현하고자 한 기능은 다음과 같다.
- Calculator 클래스
- 입력받은 정수 두 개가 양수인지 확인해주는
Operate
메서드
(음의 정수일 경우, 양의 정수를 입력할 때까지 input을 반복하여 return)- 매개변수(양의 정수 두 개와 연산자)를 입력받아 사칙연산을 해주는
check
메서드- 위 메서드에서 나온 결과값을 축적해서 저장할 리스트 필드
ResultCollection
- App 클래스의 main 메서드에서
ResultCollection
필드에 직접 접근하지 못하도록private
으로 만들되, getter와 setter 메서드를 사용해 간접적으로 필드에서 데이터를 가져오거나 수정할 수 있게 함.- App클래스
- 양의 정수 두개와 연산자를 입력받아
Operate
메서드에 넣음
(이 때, 정수가 양의 정수인지 확인하기 위해check
메서드에 넣음)- 연산자가 '/'이고, 두 번째 정수가 0일 경우 오류 메세지를 띄우고 사칙연산을 하지 않음
- 첫 번째 연산 이후, 연산을 계속 할 것인지 물어보고 "exit"을 입력하지 않으면 무한히 반복할 수 있도록
do-while문
으로 작성- 연산이 최종 종료되면
ResultCollection
에 저장된 데이터 중 가장 첫 번째 데이터를 삭제할 수 있도록 선택지를 제시.
(yes/no 외 이상한 값을 입력시 input 반복)
App 클래스의 main 메서드는 오류표시 없이 실행되었으나 첫 번째 양의 정수, 연산자, 두 번째 양의 정수까지 입력 후 다음과 같은 오류가 발생하였다.
보면 App의 main 메서드에서 입력값들을Operate 메서드
로 넘겨 실행하다가 오류가 생겨 main메서드를 중지시킨 것으로 보인다.
자세히 읽어보니 문제가 된 부분 Calculator.java:31
에 해당하는 부분은 Operate 메서드
에서 연산 마지막에 결과 값을 ArrayList.add(Object)
함수를 사용하여 리스트 필드에 저장하는 부분이었다. 이 부분에 리스트 ResultCollection
가 null이어서 접근할 수 없다는 오류로 해석을 마쳤다.
왜 ResultCollection이 null인지 알 수가 없었다.
Calculator 클래스에
private ArrayList<Double> ResultCollection;
를 입력하여 필드도 만들어주었는데 왜 오류가 나는 것인지 알 수 없었다.
컬렉션을 이렇게 생성하는 것이 아닌가? 라는 생각이 들어 공부한 내용을 복습하며 리스트 대신 큐로도 시도해보았으나 해결되지 않았다.
복습을 하다보니 리스트를 선언만 하고 생성해주지 않았음을 알게 되었다.
생성자에 새로운 리스트를 생성하는 구문을 적어줌으로써 문제를 해결할 수 있었다.
//생성자
public Calculator() {
ResultCollection = new ArrayList<Double>();
}
생성자에 ResultCollection
리스트를 생성해주자 input들을 다 받고나서 문제없이 연산이 진행되고 리스트에 저장이 되는 것을 확인할 수 있었다.
(App클래스의 main메서드의 마지막에 calculator.getResultCollection();
를 넣어 찍어볼 수 있었다.)
이 오류를 해결하며 컬렉션 타입을 다룰 때 컬렉션을 선언하고 생성까지 해줘야 한다는 것을 명심하게 되었다.
입력은 정수로 받고 있으니 대체로 값은 정수로 나올 터였다. 그럼에도 결과가 실수로 나오도록 설정한 것은 나눗셈을 했을 때 수가 나눠떨어지지않을 수 있기 때문이었다. 그러나 실제로 나눠 떨어지지않는 수들을 입력했을 때, 나머지를 제외한 몫이 나오는 것을 확인할 수 있었다.
예를 들어, 15, /, 2 를 입력했을 때 7.5가 나오기를 원했는데 7.0이 나오는 상황이 발생했다.
나는 입력을 정수로 받아 Operator
메서드에 돌리고 결과값을 double로 return하는 방식을 통해 자동형변환을 시키고 있었는데, 이것이 문제가 되는 것 같았다. result
가 마지막에 형변환이 되기때문에 정수/정수의 나눗셈에서 몫이 정수로 떨어지도록 나머지 없이 소숫점이 버려진 후, 그 이후에 실수로 변환되는 것이었다.
원인이 맞는지 확실하게 확인을 하고 해결을 하기 위해 연습용 java 파일을 만들어서 문제를 고쳐보기로 했다.
확인해보니 다음과 같은 코드에서도 7.5가 아닌 7.0이 찍히는 것을 확인했다.
public class 연습 {
public static void main(String[] args) {
int a = 15;
int b = 2;
double result = a/b;
System.out.println(result);
}
}
정수끼리의 나눗셈이 우선되고 이후에 형변환이 되는 것이 문제같았으니,
int a와 b를 먼저 형변환 시켜준 후 나눗셈연산을 시키면 될 것 같았다.
public class 연습 {
public static void main(String[] args) {
int a = 15;
int b = 2;
double result = (double)a/(double)b;
System.out.println(result);
}
}
(double)
로 형변환 시켜 나눗셈을 시키자 값이 7.5로 정상적으로 찍히는 것을 확인했다.
이를 Operator 메서드에도 적용시켜 나눗셈일 때의 조건문 부분에 다음과 같이 수정해주자 문제가 해결되었다. (대충 발췌해보자면 이렇다.)
if (Operator=='/'){
result = (double)num1 / (double)num2;
}
Java를 단기간에 집중적으로 공부하고 있다보니 중간중간 까먹는 개념들도 많고 실제로 배운 이론들을 디테일하게 다 실습해볼 수는 없어 공부한 개념들이 완벽하게 체득되지는 않는다는 기분이 들었었다.
하지만 이번에 계산기를 구현하며 마주한 여러 케이스들을 통해 좀 더 공부한 내용들을 내 것으로 만든다는 느낌이 들었다. 배운 내용을 다시 꼼꼼히 복습하여 다음에는 오류를 덜 낼 수 있도록 노력해야겠다.