πŸ“š[Java] 계산기 - μ œλ„€λ¦­μ„ ν™œμš©ν•œ κΈ°λŠ₯ ν™•μž₯

텁텁·2025λ…„ 4μ›” 21일

계산기 κΈ°λŠ₯ν™•μž₯


ꡬ쑰 λ³€κ²½

int ν˜• 두 수의 값을 κ΅¬ν•˜λ˜ Calculator κ°€ double ν˜•μ˜ 값이 μž…λ ₯돼도 μ‚¬μš© κ°€λŠ₯ν•˜λ„λ‘ ν™•μž₯μ‹œν‚¬ 것

λ„μ „κ³Όμ œμ—μ„œ κ°€μž₯ μ€‘μš”ν•œ μš”κ΅¬μ‚¬ν•­μ΄λ‹€. λ‹¨μˆœνžˆ double 둜의 ν˜•λ³€ν™˜μ΄ μ•„λ‹ˆλΌ μ œλ„€λ¦­μ„ μ μš©ν•΄μ•Ό ν•œλ‹€.
μ—¬κΈ°μ„œ μ œλ„€λ¦­μ΄λž€ ν‚€μ›Œλ“œμ— μ ‘κ·Όν•˜κΈ°λ„ 전에 λ¬Έμ œκ°€ 생긴닀.


μž…λ ₯κ°’μ˜ λ”œλ ˆλ§ˆ

2λ‹¨κ³„κΉŒμ§€μ˜ κ³„μ‚°κΈ°λŠ” Scanner 의 nextInt() λ©”μ„œλ“œλ₯Ό 톡해 숫자λ₯Ό μž…λ ₯λ°›μ•˜λ‹€.
ν•˜μ§€λ§Œ ν•΄λ‹Ή λ©”μ„œλ“œλŠ” μ •μˆ˜λ§Œ μž…λ ₯ κ°€λŠ₯ν•˜λ©° μ‹€μˆ˜λ₯Ό μž…λ ₯받을 μ‹œ InputMismatchException μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€.
κ·Έλ ‡λ‹€κ³  nextDouble() 을 μ‚¬μš©ν•˜κΈ°μ—” λ‹¨μˆœνžˆ ν˜•λ³€ν™˜μ„ ν•˜λŠ”κ²ƒμ΄ μ•„λ‹ˆλΌλŠ” μš”κ΅¬μ‚¬ν•­κ³Ό μ •μˆ˜, μ‹€μˆ˜ 두 κ°€μ§€μ˜ 선택사항을 λͺ¨λ‘ λ°˜μ˜ν•˜μ§€ λͺ» ν•˜λŠ” 것이라 μƒκ°ν–ˆλ‹€.
고민의 μ‹œκ°„μ„ 거쳐 λ¬Έμžμ—΄μ„ λ°›μ•„ μžλ£Œν˜•μ— 맞게 νŒŒμ‹±ν•˜λŠ” 방법을 μ„ νƒν–ˆλ‹€.


NumberParser

public class NumberParser {

    public Number parseNumber(String number){
        if(number.contains(".")){
            return Double.parseDouble(number);
        } else {
            return Integer.parseInt(number);
        }
    }

}

λ¬Έμžμ—΄μ„ ν•΄λ‹Ή νƒ€μž…μœΌλ‘œ λ³€ν™˜ μ‹œν‚€λŠ” parseNumber() λ©”μ„œλ“œλ₯Ό κ°€μ§„ Parserλ₯Ό λ§Œλ“€μ—ˆλ‹€.
μ†Œμˆ˜μ μ„ λ‚˜νƒ€λ‚΄λŠ” . 기호λ₯Ό κΈ°μ€€μœΌλ‘œ 래퍼클래슀 Double ν˜•κ³Ό Integer νƒ€μž…μœΌλ‘œ λ³€ν™˜μ‹œμΌ°κ³  ν•˜λ‚˜μ˜ λ©”μ„œλ“œμ—μ„œ μ„œλ‘œ λ‹€λ₯Έ 숫자 νƒ€μž…μ„ λ°˜ν™˜ν•  수 없기에 Number λ₯Ό λ°˜ν™˜ νƒ€μž…μœΌλ‘œ μ„€μ •ν•˜μ—¬ μ²˜λ¦¬ν–ˆλ‹€.


Number νƒ€μž…μ˜ ν—ˆμ 

'μ œλ„€λ¦­μ„ μ¨μ•Όν•œλ‹€' λŠ” 압박감에 μ–΅μ§€λ‘œ μ œλ„€λ¦­μ„ ν™œμš©ν•˜λ €λ‹€ λ³΄λ‹ˆ 였히렀 μ œλ„€λ¦­μ˜ μž₯점을 살리지 λͺ»ν•˜κ²Œ λ˜μ—ˆλ‹€.

import java.util.ArrayList;
import java.util.List;

public class ArithmeticCalculator<T extends Number> {
    private enum OperatorType {
        PLUS("+"), MINUS("-"), TIMES("*"), DIVINED("/");

        private final String oper;

        OperatorType(String oper) {
            this.oper = oper;
        }

        public String getOper() {
            return oper;
        }

        public static OperatorType operChoice(String c){
            for(OperatorType oper : OperatorType.values()) {
                if (oper.getOper().equals(c)){
                    return oper;
                }
            }
            throw new IllegalArgumentException("ν•΄λ‹Ήν•˜λŠ” μ—°μ‚°μžκ°€ μ—†μŠ΅λ‹ˆλ‹€.");
        }
    }

    private final List<Number> operationResults = new ArrayList<>();

    public void clearOperationResults() {
        operationResults.clear();
    }

    public void removeOperationResult(int i) {
        operationResults.remove(i);
    }

    public void setOperationResults(Number sum) {
        operationResults.add(sum);
    }

    public Number getOperationResult() {
        return operationResults.get(operationResults.size()-1);
    }

    public List<Number> getOperationResults() {
        return operationResults;
    }

    public void checkNegative(T num1, T num2) throws IllegalArgumentException{
        if(num1.doubleValue() < 0 || num2.doubleValue() < 0){
            throw new IllegalArgumentException("μž…λ ₯값은 μŒμˆ˜κ°€ 될 수 μ—†μŠ΅λ‹ˆλ‹€. (μž…λ ₯κ°’>=0)");
        }
    }

    public void calculator (T num1, T num2, String c){
        OperatorType oper = OperatorType.operChoice(c);
        checkNegative(num1, num2);

        switch (oper) {
            case PLUS:
                setOperationResults(num1.doubleValue() + num2.doubleValue());
                break;

            case MINUS:
                setOperationResults(num1.doubleValue() - num2.doubleValue());
                break;

            case TIMES:
                setOperationResults(num1.doubleValue() * num2.doubleValue());
                break;

            case DIVINED:
                if(num2.doubleValue() == 0){
                    throw new IllegalArgumentException("λ‚˜λˆ„κΈ° μ§„ν–‰ μ‹œ 두 번째 값이 0이 될수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.");
                }
                setOperationResults(num1.doubleValue() / num2.doubleValue());
                break;
        }

        System.out.println("계산 κ²°κ³ΌλŠ”: " + getOperationResult() + " μž…λ‹ˆλ‹€.");

    }
}
import java.util.List;
import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        NumberParser np = new NumberParser();
        Scanner sc = new Scanner(System.in);
        ArithmeticCalculator<Number> ac = new ArithmeticCalculator();

        while(true) {
            try {
                System.out.println("계산을 μ§„ν–‰ν•  두 숫자λ₯Ό μž…λ ₯ν•˜μ„Έμš”. (μž…λ ₯κ°’ >=0)");
                System.out.print("첫 번째 μž…λ ₯κ°’: ");
                Number num1 = np.parseNumber(sc.nextLine());
                System.out.print("두 번째 μž…λ ₯κ°’: ");
                Number num2 = np.parseNumber(sc.nextLine());
                System.out.println("계산에 λ§žλŠ” μ—°μ‚°κΈ°ν˜Έ(+, -, *, /)λ₯Ό μž…λ ₯ν•˜μ„Έμš”!");
                String c = sc.nextLine();
                ac.calculator(num1, num2, c);
                System.out.println("숫자λ₯Ό μž…λ ₯ν•˜λ©΄ μ§€κΈˆκΉŒμ§€μ˜ 계산값 쀑 μž…λ ₯값보닀 큰 값을 좜λ ₯ν•©λ‹ˆλ‹€.");
                Number num3 = np.parseNumber(sc.nextLine());

                PrintList printList = () -> {
                    List<Number> f = ac.getOperationResults().stream().filter(num -> num.doubleValue() > num3.doubleValue())
                            .toList();
                    if(f.isEmpty()){
                        System.out.println("μž…λ ₯값보닀 큰 값이 μ—†μŠ΅λ‹ˆλ‹€.");
                    } else {
                        System.out.println("μž…λ ₯값보닀 큰 값은: " + f);
                    }
                };
                printList.prt();

                System.out.println("κ³„μ†ν•΄μ„œ 계산을 μ§„ν–‰ν•˜μ‹œλ €λ©΄ μ—”ν„°λ₯Ό μž…λ ₯ν•˜μ„Έμš”.('exit' λ₯Ό μž…λ ₯μ‹œ μ’…λ£Œλ©λ‹ˆλ‹€.)");
                String check = sc.nextLine();
                if(check.equals("exit")){
                    break;
                }

            } catch (NumberFormatException e) {
                System.out.println("잘λͺ»λœ μž…λ ₯μž…λ‹ˆλ‹€.");
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }

        }

        sc.close(); //μŠ€μΊλ„ˆ μ’…λ£Œ μœ„μΉ˜ μˆ˜μ •

    }
}

ArithmeticCalculator<T extends Number>λΌλŠ” μ œλ„€λ¦­ 클래슀λ₯Ό μž‘μ„±ν–ˆμ§€λ§Œ κ²°κ΅­ λ§€κ°œλ³€μˆ˜λ₯Ό Number 둜 λ°›λŠ” 것과 λ‹€λ₯Ό λ°” μ—†λ‹€.
ν˜•μ‹λ§Œ μ œλ„€λ¦­μ΄μ§€ μ‹€μ§ˆμ μΈ νƒ€μž… μΆ”μƒν™”μ˜ 이점을 μ „ν˜€ λˆ„λ¦¬μ§€ λͺ»ν•œ μ½”λ“œμΈ 것이닀.
λ˜ν•œ μž…λ ₯κ°’ νŒŒμ‹±μ„ Number둜 κ³ μ •ν–ˆκΈ°μ— calculator() λ©”μ„œλ“œμ—μ„  연산을 μœ„ν•œ λ‹€μš΄μΊμŠ€νŒ…μ΄ ν•„μš”ν–ˆλ‹€.
λ§Œμ•½ μ œλ„€λ¦­μ„ 의미 있게 μ“°κ³ μž ν–ˆλ‹€λ©΄ num1, num2κ°€ int-int, int-double, double-int, double-double 쑰합일 경우λ₯Ό 각각 κ³ λ €ν•΄ νƒ€μž…λ³„λ‘œ 처리λ₯Ό ν•΄μ•Ό ν–ˆκ² μ§€λ§Œ κ·Έλ ‡κ²Œ κ΅¬ν˜„ν•  μ‹œ μ½”λ“œ 가독성은 κΈ‰κ²©νžˆ λ–¨μ–΄μ§€κ³  μœ μ§€λ³΄μˆ˜λ„ μ–΄λ €μ›Œμ§€κ²Œ λœλ‹€.
결둠적으둜 ν˜„μž¬ κ΅¬μ‘°λŠ” μ œλ„€λ¦­μ„ μ“°κΈ° μœ„ν•œ 섀계 μžμ²΄κ°€ 잘λͺ»λλ‹€κ³  μƒκ°λœλ‹€.


enum 의 μ•„μ‰¬μš΄ ν™œμš©

enum(μ—΄κ±°ν˜•)을 μ‚¬μš©μ‹œ λ‹€μ–‘ν•œ μž₯점을 얻을 수 μžˆλ‹€.

enum의 μž₯점
1. 의미 μžˆλŠ” μƒμˆ˜λ₯Ό κ·Έλ£Ήν™” ν•  수 μžˆλ‹€.

  • μ˜ˆμ‹œ) μš”μΌ(MONDAY, TUESDAY ...) λ“±
  1. switchλ¬Έκ³Ό 잘 μ–΄μšΈλ¦°λ‹€.
    • 쑰건 λΆ„κΈ°μ—μ„œ enum μ‚¬μš©μ‹œ 가독성도 μ’‹κ³  관리도 μ‰¬μ›Œμ§„λ‹€.
  2. κ°’λΏλ§Œ μ•„λ‹ˆλΌ λ™μž‘λ„ 담을 수 μžˆλ‹€.
    • enum μ•ˆμ— μƒμ„±μž, ν•„λ“œ, λ©”μ„œλ“œλ„ 넣을 수 μžˆμ–΄ λ‹¨μˆœν•œ κ°’ μ΄μƒμ˜ 의미λ₯Ό κ°€μ§„λ‹€.
  3. μœ μ§€λ³΄μˆ˜μ™€ ν™•μž₯성이 μ’‹λ‹€.
    • μƒˆλ‘œμš΄ 값이 ν•„μš”ν•΄λ„ κΈ°μ‘΄ μ½”λ“œλ₯Ό 거의 κ±΄λ“œλ¦¬μ§€ μ•Šκ³  enum 에 μƒˆλ‘œμš΄ μƒμˆ˜λ§Œ μΆ”κ°€ν•˜λ©΄ λœλ‹€.

enum μ‚¬μš©μ— μ΅μˆ™μΉ˜ μ•Šμ•„ κ²°κ΅­ 1, 2번의 두 κ°€μ§€ μž₯점밖엔 κ΅¬ν˜„μ„ ν•˜μ§€ λͺ»ν–ˆλ‹€.
μ—°μ‚° λ©”μ„œλ“œλ₯Ό 넣어보렀 λ…Έλ ₯은 ν–ˆμ—ˆμœΌλ‚˜ μ—¬κΈ°μ„œλ„ Number ν˜•μ΄ 발λͺ©μ„ μž‘μ•˜λ‹€.
enum 에 μ—°μ‚° λ©”μ„œλ“œλ₯Ό λ„£λŠ” μ΄μœ λŠ” 연산을 enum μ•ˆμ—μ„œ μ²˜λ¦¬ν•˜κ³ μž ν•˜λŠ” λͺ©μ μ΄μ§€λ§Œ Number λ₯Ό μ—°μ‚°ν•˜κΈ° μœ„ν•΄μ„  ν˜•λ³€ν™˜μ΄ ν•„μš”ν•˜λ‹€λŠ” μ œμ•½μ΄ μžˆμ—ˆκΈ°μ— ν˜„μž¬ μƒν™©μ—μ„œμ˜ κ΅¬ν˜„μ€ λ‚΄ λŠ₯λ ₯ λ²”μœ„λ₯Ό λ²—μ–΄λ‚œλ‹€κ³  λŠκΌˆλ‹€.


λ‚΄κ°€ 감당할 수 μžˆλŠ” λ²”μœ„ λ‚΄μ—μ„œ μš”κ΅¬μ‚¬ν•­μ„ μ΅œλŒ€ν•œ λ°˜μ˜ν•˜λ € λΆ€λ‹¨νžˆ λ…Έλ ₯ν–ˆλ‹€.

κ·ΈλŸ¬λ‚˜ ꡬ쑰λ₯Ό μ„€κ³„ν•˜κ³  κ΅¬ν˜„μ— λ“€μ–΄κ°€λŠ” μ€€λΉ„ 단계가 μ΅μˆ™ν•˜μ§€ μ•Šμ•„ λ¬΄μž‘μ • λΆ€λ”ͺνžˆλ“― μž‘μ—…μ„ 이어가닀 λ³΄λ‹ˆ 마무리 단계에 이λ₯΄λŸ¬μ„œμ•Ό λ¬Έμ œμ μ„ λ°œκ²¬ν•˜κ²Œ λ˜μ—ˆκ³  κ·Έ μ‹œμ μ—λŠ” 이미 λ‚΄κ°€ ν•΄κ²°ν•  수 μžˆλŠ” λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ μ½”λ“œκ°€ λ˜μ–΄ μžˆμ—ˆλ‹€.

enum, λžŒλ‹€μ‹, Stream μ—­μ‹œ 기본적인 μˆ˜μ€€μ—μ„œλ§Œ μ‚¬μš©ν–ˆμ„ 뿐 각각의 νŠΉμ„±κ³Ό ν™œμš©λ²•μ„ μΆ©λΆ„νžˆ μ΄ν•΄ν•˜μ§€ λͺ»ν•œ μƒνƒœμ˜€κΈ°μ— κ·Έ μž₯점과 κ°€λŠ₯성을 μ‚΄λ¦¬κΈ°λ³΄λ‹€λŠ” κ΅¬ν˜„μ— κΈ‰κΈ‰ν•œ λͺ¨μŠ΅μ΄μ—ˆλ‹€.

μ—¬λŸ¬λͺ¨λ‘œ 아쉬움이 λ‚¨λŠ” κ³Όμ œμ˜€μ§€λ§Œ μ€‘μ μ μœΌλ‘œ ν•™μŠ΅ν•΄μ•Ό ν•  λ°©ν–₯을 λΆ„λͺ…νžˆ μ•Œκ²Œ λ˜μ—ˆλ‹€λŠ” 점에 의의λ₯Ό λ‘κ³ μž ν•œλ‹€.

profile
μ°¨κ·Όμ°¨κ·Ό

5개의 λŒ“κΈ€

comment-user-thumbnail
2025λ…„ 4μ›” 21일

"κ·Έ μ‹œμ μ—λŠ” 이미 λ‚΄κ°€ ν•΄κ²°ν•  수 μžˆλŠ” λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ μ½”λ“œκ°€ λ˜μ–΄ μžˆμ—ˆλ‹€."
β†’ λ¦¬νŒ©ν„°λ§μ— λŠ¦μ€ λ•ŒλŠ” μ—†μŠ΅λ‹ˆλ‹€!!!

enum을 λ³„λ„μ˜ ν΄λž˜μŠ€κ°€ μ•„λ‹Œ λ‚΄λΆ€ 클래슀둜 μ •μ˜ν•œ νŠΉλ³„ν•œ μ΄μœ κ°€ μžˆλ‚˜μš”?

μš”κ΅¬μ‚¬ν•­μ— "Calculator ν΄λž˜μŠ€μ— μ €μž₯된 μ—°μ‚° κ²°κ³Όλ“€ 쀑 κ°€μž₯ λ¨Όμ € μ €μž₯된 데이터λ₯Ό μ‚­μ œν•˜λŠ” κΈ°λŠ₯을 κ°€μ§„ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„"라고 μžˆλŠ”λ° 여기에 μ—†λŠ” λ©”μ†Œλ“œμΈκ°€μš”?

sumListλŠ” μ™œ 이름이 sumListμΈκ°€μš”? sum을 포함해 λ‹€λ₯Έ λͺ¨λ“  κ²°κ³Όλ₯Ό 담을 수 μžˆλŠ” 것 μ•„λ‹Œκ°€μš”?

1개의 λ‹΅κΈ€