관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

[Spring반] 중간시험 10 - Java 실기 시험 및 문제 풀이 2 : 문제 3번 <사칙연산 계산기> 본문

개발 포트폴리오/수료증 및 시험

[Spring반] 중간시험 10 - Java 실기 시험 및 문제 풀이 2 : 문제 3번 <사칙연산 계산기>

huenuri 2024. 12. 9. 08:36

이 문제를 풀다가 아마 졸려서 취침하게 될 것 같다. 풀 수 있는 데까지 풀고 다음날 아침에 일어나서 하면 된다. 이제 3번 문제부터 풀어보겠다.


 

 

 

 

Java 실기 시험 두 번째

 

문제 3번

두 개의 정수를 입력받은 후 입력한 연산자에 따라 연산결과가 나오는 프로그램을 작성하시오.

 

 

 

방법 1 - 클래스 하나로 작성하기

 

 

 

 

 

 

 

코드 설명

  1. 입력값 처리
    • Scanner를 사용해 두 정수와 연산자를 입력받음
    • 연산자는 next().charAt(0)을 사용하여 첫 번째 문자만 처리
  2. 연산자에 따른 분기
    • switch-case를 사용해 입력된 연산자에 따라 연산을 수행
    • 기본 값(default)으로는 잘못된 연산자 입력에 대해 오류 메시지 출력
  3. 나눗셈 처리
    • 나눗셈의 경우, 0으로 나누는 오류를 방지하기 위해 조건문(if) 추가
    • 결과를 실수(double)로 처리하여 정확한 계산 수행
  4. 프로그램 안정성
    • 모든 입력과 연산에 대해 예외 상황을 처리하여 프로그램이 중단되지 않도록 설계

 

 

 

방법 2 - 클래스를 나누어서 작성하기 + 새로운 연산자 추가하기

이 방법은 솔직히 많이 어려워서 푸는데 시간이 많이 걸리고 코드 오류가 많이 났다. 

 

 

 

 

 

 

코드 구조

  • Operations 클래스
    • 연산 메서드(덧셈, 뺄셈, 곱셈, 나눗셈)를 정의
    • 모든 메서드는 static으로 선언하여, 인스턴스 생성 없이 직접 호출 가능
  • Calculator 클래스
    • 사용자 입력을 처리하고, 입력된 연산자를 기반으로 ArithmeticOperations 클래스의 메서드를 호출

 

 

장점

  1. 코드의 역할 분리
    • Operations 클래스는 연산 기능만 담당
    • Calculator 클래스는 사용자 입력과 프로그램 흐름 제어를 담당
  2. 유지보수 용이
    • 연산 로직에 변경이 필요하면 Operations 클래스만 수정하면 됨
  3. 확장성
    • 새로운 연산(예: 나머지 %, 제곱 ^)을 추가할 때, Operations에 메서드를 추가하고 switch문에 추가하면 쉽게 확장 가능

 

% 연산자를 사용했을 때 소수형이 아닌 정수형으로 반환되도록 만들고 싶어졌다.


 

 

 

 

방법 3 - 나머지 연산자만 정수형으로 반환하기

네 가지 연산 외에 % 연산자를 한번 추가했다. 그리고 정수형으로 받기 위해 반환값을 바꾸었지만 형 변환을 할 때 계속 오류가 뜨는 문제가 발생했다. 

 

 

 

오류가 발생하는 이유는 modulo 메서드가 int 타입을 매개변수로 받도록 설계되었지만, 호출 시 num1과 num2가 double 타입으로 전달되었기 때문이다. double 값을 int로 변환하지 않으면, modulo 메서드와 호출 간의 타입 불일치로 인해 컴파일 오류가 발생한다.

 

 

해결 방법

1. modulo 메서드의 매개변수 타입을 double로 변경

  • 메서드 호출 시 타입 변환 없이 사용할 수 있도록 modulo 메서드의 매개변수를 double로 변경
 
public static double modulo(double a, double b) {
    return a % b;
}

 

 

2. 호출하는 쪽에서 명시적 형변환

  • modulo 메서드의 매개변수를 그대로 int로 유지하려면, 호출하는 쪽에서 전달값(num1, num2)을 int로 명시적 형변환
case '%':
    result = Operations.modulo((int) num1, (int) num2); // 명시적 형변환
    System.out.println("연산 결과: " + result);
    break;

 

 

각 방법의 차이점

방법 장점 단점
메서드 매개변수를 double로 변경 int와 double 모두 처리 가능. 추가 변환 없이 다양한 타입에 대해 유연하게 동작 나머지 연산이 double로 수행되므로, 값이 소수점까지 포함될 수 있음
명시적 형변환 추가 나머지 연산을 항상 int 타입으로 제한. 결과 값이 정수로 보장됨 호출하는 모든 코드에서 형변환이 필요. 입력값 손실 가능성(소수점 이하 절삭)

 

 

 

이렇게 코드를 수정한 후 실행해보았다.

 

 

 

하지만 이렇게 수정해도 정수형으로 나오지 않았다. 결과값을 int형으로 받도록 코드를 따로 작성해 주었다.


 

 

 

코드 수정하기

 

 

 

 

 

이제 정수형으로 잘 출력된다.

 

 

하지만 나눗셈을 할 때 소수점 첫째 자리까지만 나오도록 만들고 싶다.


 

 

 

 

방법 4 - 나눗셈 연산 시 소수점 첫째 자리까지만 출력하도록 하기

나눗셈 결과를 소수점 첫째 자리까지만 출력하려면 **printf**를 사용하거나 DecimalFormat 클래스를 활용할 수 있다.

 

1. printf를 사용하는 방법

printf는 포맷을 지정하여 출력할 수 있는 간단한 방법이다. 

case '/':
    if (num2 != 0) {
        result = Operations.divide(num1, num2);
        System.out.printf("연산 결과: %.1f\n", result); // 소수점 첫째 자리까지 출력
    } else {
        System.out.println("0으로 나눌 수 없습니다.");
    }
    break;

 

 

 

2. DecimalFormat을 사용하는 방법

DecimalFormat 클래스는 숫자를 원하는 형식으로 포맷팅할 때 사용돼.

import java.text.DecimalFormat;

// 나눗셈 케이스
case '/':
    if (num2 != 0) {
        result = Operations.divide(num1, num2);
        DecimalFormat df = new DecimalFormat("#.0"); // 소수점 첫째 자리까지 포맷
        System.out.println("연산 결과: " + df.format(result));
    } else {
        System.out.println("0으로 나눌 수 없습니다.");
    }
    break;

 

하지만 이때 주의할 점은 result를 반환할 때 문자열 결합 연산자를 사용해서는 안된다. 만약 사용 시 이러한 오류가 뜬다.

 

 

 

printf는 형식 지정자를 사용한 출력 메서드인데, 문자열 결합(+)과 함께 사용할 수 없다. System.out.printf에서 형식 지정자와 값을 따로 전달해야 한다.

이제 전체 코드를 올려보면 다음과 같다.


 

 

 

전체 코드 

 

 

이제 드디어 해결했다. 이 문제 하나 푸는데 1시간 반도 넘게 걸렸다.


 

 

 

 

학습을 마치고

오늘 새벽에 2시쯤 문제를 풀어보려다가 문제만 써놓고 아침 7시에 일어나서 다시 풀어보았다. 이 문제는 혼자서 풀기는 어려워서 자료를 참고하며 풀었다. 그리고 여러 가지 방법을 연구하며 이제 드디어 내 마음에 드는 코드로 완성했다. 이렇게 코드를 수정하며 만들어가는 과정이 즐겁다.

비록 힘들기는 했으나 수십 번 코드를 수정하며 정말 많은 것들을 배울 수 있었다.