Java의 거대 정수를 담을 수 있는 BigInteger

JAVA|2018. 7. 31. 23:36

대학교 학창시절에 BigInteger만들기를 자료구조 시간에 C로 만들어 본적이 있다.

그리고 실질적으로 실무에서는 Long값을 벗어난 데이터를 담아서 사용해본적이 없어 자바의 BigInteger라는 객체가 존재하는지 몰랐다.

매주 진행하는 알고리즘 스터디에서 문제를 풀다가 Long값 이상의 데이터가 필요해서 찾다가 사용하게 되었다.

몇 가지 정리해보자.

BigInteger 객체 생성 방법
팩토리 메서드와 기존 constant 객체로써 제공하는 방법으로 BigInteger객체를 만들 수 있다.

1
2
3
4
5
6
7
8
9
10
// Constant
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger ten = BigInteger.TEN;
        
// 생성자로 생성
BigInteger ten2 = new BigInteger("10");
        
// 팩터리 메스드로 생성
BigInteger ten3 = BigInteger.valueOf(10);
cs


그럼 생성자와 Constant 그리고 팩터리 메서드로 만드는 경우의 차이는 무엇인가? 
Constant와 팩터리 메스드의경우 같은 계속 같은 객체가 나오게 될 것이고, 생성자의 경우 매번 다른 객체가 나온다.

1
2
3
4
5
6
7
8
9
// 비교
System.out.println(ten == ten2);
System.out.println(ten3 == ten2);
System.out.println(ten3 == ten);
 
// 결과
false
false
true
cs


Immutable
그리고 BigInteger의 경우 Immutable 속성으로 인해 연산을 통해 나온 결과는 기존의 BigInteger 객체가 변경되는 것이 아니라 새로운 객체가 만들어진다.

사칙연산
우선 BigInteger는 사칙연산을 바로 사용할 수 없다.
사칙연산을 사용하기 위해서는 다음과 같은 메서드등을 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
// 덧셈
System.out.println(ten2.add(ten3));
        
// 뺄셈
System.out.println(ten2.subtract(ten3));
        
// 곱셈
System.out.println(ten2.multiply(BigInteger.ONE));
 
// 나누기
System.out.println(ten.divide(BigInteger.ONE));
cs


다음번에는 이 BigInteger를 이용해서 피보나치 수열을 한번 풀어보자.

'JAVA' 카테고리의 다른 글

Java의 거대 정수를 담을 수 있는 BigInteger  (0) 2018.07.31

댓글()

Java List 인터페이스 중 CopyOnWriteArrayList 소개

JAVA/JAVA 관련|2018. 6. 3. 16:36

자바에는 크게 4개의 List 인터페이스를 구현한 클래스가 있다.

- Vector, ArrayList, LinkedList, CopyOnWriteArrayList


그 중 가장 생소한 이름이 있는데 CopyOnWriteArrayList이다. CopyOnWriteArrayList는 그냥 ArrayList랑 다르길래 화려한 이름을 가지고 있는걸까?


ArrayList vs CopyOnWriteArrayList

일반 ArrayList의 경우 스레드에 안전하게 설게되어 있지 않기때문에 만약 스레드 처리가 필요한 List의 경우에 Vector를 사용하거나 ArrayList에 synchroized를 사용하여 처리하였다. 하지만 자바 1.5부터 있던 CopyOnWriteArrayList를 쉽게 이문제를 해결할 수 있다.


CopyOnWriteArrayList의 경우 ArrayList와 모든 부분이 동일하나 어디에 컨텐츠를 전달할 때 컨텐츠를 복사해서 전달한다. 그렇기 때문에 전달 후 해당 List의 내용이 변경될 것을 우려하지 않아도 된다.


CopyOnWriteArrayList는 그냥 ArrayList보다 물론 부담이 있을수 있다. 하지만 잘못설계된 동기화코드보다 더 안전하고 비용이 절감될 수도 있다.


그리고 CopyOnWriteArrayList는 객체를 매번 복사하는 것이 아니라 전달시 해당 상태를 스냅샷으로 가지고 있는 방식으로 진행한다.

자세한 내용은 아래 사이트를 참조하면 도움이 될 것이다.


https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

댓글()

Deque를 직접 구현해보기

IT 지식/자료구조|2018. 6. 2. 09:34

큐는 삽입과 삭제가 리스트의 한쪽 방향에서만 이루어지지만 deque는 리스트의 양쪽 끝 모두에서 이루어질 수 있다.


따라서 양쪽 방향 모두 삽입과 삭제가 이루어질 수 있으므로 기존의 큐나 스택으로 사용할 수 있어 유연하게 사용할 수 있다.


사진출처 : https://dh00023.github.io/algorithm/ds/2018/04/25/algorithm-10/





이런 Deque를 직접 구현해 보자.





우선 Deque의 기능을 정리한 인터페이스이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package practice3;
 
public interface Deque<T> {
    public void addFirst(T item);
 
    public void addLast(T item);
 
    public T removeFirst();
 
    public T removeLast();
 
    public T peekFirst();
 
    public T peekLast();
 
    public boolean isEmpty();
 
    public int size();
 
    public String toString();
 
}
 
cs





그리고 인터페이스를 가지고 구현된 Deque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package practice3;
 
import java.util.ArrayList;
import java.util.List;
 
public class LinkedDeque<T> implements Deque<T>{
    private static class Node<T> {
        private T item;
        private Node<T> next;
        private Node<T> prev;
 
        private Node() {
            next = null;
            prev = null;
        }
 
        private Node(T item) {
            this.item = item;
            next = null;
            prev = null;
        }
    }
 
    private Node<T> front;
    private Node<T> rear;
    private int size;
 
    public LinkedDeque() {
        front = null;
        rear = null;
        size = 0;
    }
 
    @Override
    public void addLast(T item) {
        Node<T> node = new Node<>(item);
        
        if (front == null && rear == null) {
            addFirstItem(node);
        } else {
            rear.next = node;
            node.prev = rear;
            rear = node;
            size++;
        }
    }
 
    @Override
    public void addFirst(T item) {
        Node<T> node = new Node<>(item);
        
        if (front == null && rear == null) {
            addFirstItem(node);
        } else {
            front.prev = node;
            node.next = front;
            front = node;
            size++;
        }
    }
    
    private void addFirstItem(Node<T> item) {
        front = item;
        rear = item;
        size = 1;
    }
 
    @Override
    public boolean isEmpty() {
        return size == 0;
    }
 
    @Override
    public T removeFirst() {
        T item = null;
        if (size == 0) {
            throw new java.util.NoSuchElementException("peek(): deque empty");
        } else if (size == 1) {
            item = front.item;
            front = null;
            rear = null;
            size = 0;
        } else {
            item = front.item;
            front = front.next;
            front.prev = null;
            size--;
        }
        
        return item;
    }
 
    @Override
    public T removeLast() {
        T item = null;
 
        if (size == 0) {
            throw new java.util.NoSuchElementException("peek(): deque empty");
        } else if (size == 1) {
            item = rear.item;
            front = null;
            rear = null;
            size = 0;
        } else {
            item = rear.item;
            rear = rear.prev;
            rear.next = null;
            size--;
        }
        
        return item;
    }
 
    @Override
    public T peekFirst() {
        if (size == 0)
            throw new java.util.NoSuchElementException("peek(): deque empty");
        return front.item;
    }
 
    @Override
    public T peekLast() {
        if (size == 0)
            throw new java.util.NoSuchElementException("peek(): deque empty");
        return rear.item;
    }
 
    @Override
    public int size() { return size; }
 
    @Override
    public String toString() {
        if (0 == size) {
            return "";
        } else {
            List<String> result = new ArrayList<>();
            Node<T> current;
            current = front;
            if (1 == size) {
                return current.item.toString();
            } else {
                while (current != null) {
                    result.add(current.item.toString());
                    current = current.next;
                }
                
                return String.join(",", result);
            }
            
        }
    }
 
    public String reverse() { // 역순으로 출력
        if (0 == size) {
            return "";
        } else {
            List<String> result = new ArrayList<>();
            Node<T> current;
            current = rear;
            if (1 == size) {
                return current.item.toString();
            } else {
                while (current != null) {
                    result.add(current.item.toString());
                    current = current.prev;
                }
                
                return String.join(",", result);
            }
            
        }
    }
 
}
 
cs




그리고 이 deque를 가지고 테스트를 진행할 Main클래스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package practice3;
 
import java.util.Scanner;
 
public class Main {
    public static void main(String[] args) {
        System.out.println("Enter a command: af(addFirst), al(addLast),\n"
                + "rf(removeFirst), rl(removeLast), pf(peekFirst), pl(peekLast),\n" + "p(rint), r(verse), or q(uit)");
        System.out.print("> ");
 
        Scanner input = new Scanner(System.in);
        String command = input.next();
        LinkedDeque<Integer> deque = new LinkedDeque<Integer>();
        int item;
 
        while (!command.equals("q")) {
            if (command.equals("af")) {
                item = input.nextInt();
                deque.addFirst(item);
            } else if (command.equals("al")) {
                item = input.nextInt();
                deque.addLast(item);
            } else if (command.equals("rf"))
                deque.removeFirst();
            else if (command.equals("rl"))
                deque.removeLast();
            else if (command.equals("s"))
                System.out.println("size: " + deque.size());
            else if (command.equals("pf"))
                System.out.println("Front of the deque: " + deque.peekFirst());
            else if (command.equals("pl"))
                System.out.println("Rear of the deque: " + deque.peekLast());
            else if (command.equals("r"))
                System.out.println(deque.reverse());
            else if (command.equals("p"))
                System.out.println(deque);
            System.out.print("> ");
            command = input.next();
        }
        System.out.println("Commands Terminated.");
        input.close();
    }
}
 
cs





출력결과


Enter a command: af(addFirst), al(addLast),

rf(removeFirst), rl(removeLast), pf(peekFirst), pl(peekLast),

p(rint), r(verse), or q(uit)

> af 20

> af 30

> af 10

> p

10,30,20

> rf

> p

30,20

> rl

> p

30

> al 33

> al 22

> p

30,33,22

> r

22,33,30

> p

30,33,22

> af 44

> al 88

> p

44,30,33,22,88

> rl

> rf

> p

30,33,22

> rf

> p

33,22

> rl

> p

33

> q

Commands Terminated.




다음 시간에는 이것을 이용해 버켓 정렬을 구현해보자.

댓글()

규칙 55 - 신중하게 최적화하라

JAVA/Effective Java|2018. 5. 29. 23:49

모든 프로그래머가 알아둬야 하는 최적화에 관련된 격언이 있다.

1. 맹목적인 어리석음을 비롯한 다른 어떤 이유보다도, 효율성이라는 이름으로 저질러지는 죄악이 더 많다.
2. 97%는 효율성을 잊어버려라.  섣부른 최적화는 모든 악의 근원이다.

그리고 프로그램을 작성하면서 기준을 삼아야 할 내용에 대해 소개한다.

[기준]
빠른 프로그램을 만들려고 처음부터 노력하지말고, 좋은 프로그램을 만들려 노력하라.
-> 좋은 구조를 가진 프로그램은 빠른게 변경하는데 어렵지 않다.
-> 정보은닉의 원칙을 지키는 것이 좋은 구조를 갖는것에 첫 번째 항목이다.

설계를 할 떄는 성능을 제약할 가능성이 있는 결정들을 피하라.
-> 특히 통신 API, 프로토콜 정의서는 변경하기 어렵기 때문에, 신중하게 코딩해야한다.

API를 설계할 떄 내리는 결정들이 성능에 어떤 영향을 끼칠지를 생각하라.
-> public 자료형을 무분별하게 사용하면 잘못된 객체 생성등으로 인해 성능에 이슈가 생길 수 있다.


코드를 최적화한 이후에 코드가 성능이 좋아졌는지 확인을 해야하는데, 전통적인 정적 컴파일 언어들에 비해, 프로그래머가 작성한 코드와 CPU가 실행하는 코드 사이의 "의미론적 차이"가 훨씬 크기 때문에 최적화 결과로 성능이 얼마나 좋아질지 안정적으로 예측하기 어렵다.
-> 특히 자바의 경우 JVM 구현마다, 릴리즈마다, 프로세스 마다 다르다. 
-> JVM 구현이나 하드웨어 플랫폼마다 다른 성능을 내기 때문에 타협적 결정을 내려야 할 때가 있다.




결론을 내면, 자잘한 성능을 고치려고 노력하지말고 구조적 알고리즘 문제를 먼저 생각하라. 잘못된 알고리즘 선택으로 인해 잘못 설계된 프로그램은 자잘한 성능개선으로 문제를 잡을 수 없기 때문이다.


출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙55 인용.

댓글()

Stack을 이용한 문장 완성도 판별 프로그램

IT 지식/자료구조|2018. 5. 27. 21:05

개발을 진행하다보면 기본에 대해 잊어갈때가 있다.

잊지 않기위해 오늘 부터 매주 하나씩 자료구조를 이용한 문제를 풀어봐야겠다.

오늘은 Stack 첫번째 시간으로 문장의 완성도를 확인하는 프로그램을 작성하여 보자.

[제약사항]
- {[(에 대한 괄호들이 정상적으로 닫혀있어야 한다.
- 주석 //, /* 안에 포함된 내용은 무시한다.
- "" double quote에 들어있는 내용을 무시한다.

간단한 프로그램이라 설명은 생략한다.



- Text를 읽고 판별을 진행하는 Main 클래스



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package practice1;
 
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
 
public class Main {
    
    public static void main(String[] args) {
        List<String> fileList = Arrays.asList("practice1_file/paren1.txt""practice1_file/paren2.txt""practice1_file/paren3.txt");
        List<String> readText = new ArrayList<>();
        
        for (String file : fileList) {
            readText(file, readText);
            System.out.println(file + " : " + checkSentence(readText));
            readText.clear();
        }
        
    }
    
    /**
     * @param readText
     * @return
     */
    public static boolean checkSentence(List<String> readText) {
        Stack<BracketType> brackets = new Stack<>();
        boolean isMultiComment = false;
        boolean isDoubleQuote = false;
        
        for (String str : readText) {
            int oneLineCommentIndex = str.indexOf("//");
            
            // line 주석 체크
            if (oneLineCommentIndex > 0) {
                str = str.substring(0, oneLineCommentIndex);
            } else if (oneLineCommentIndex == 0) {
                continue;
            }
            
            for (int i = 0; i < str.length(); i++) {
                char c = str.charAt(i);
                
                // 멀티 라인 주석일 경우
                if (isMultiComment) {
                    if ( c == '*' && i + 1 < str.length() && str.charAt(i + 1== '/' ) {
                        isMultiComment = false;
                        i += 1;
                    } else {
                        continue;
                    }
                }
                
                // " 시작인 경우
                if (isDoubleQuote) {
                    if ( c == '"' ) {
                        isDoubleQuote = false;
                        continue;
                    } else {
                        continue;
                    }
                }
                
                // ", /*
                if (c == '"') {
                    isDoubleQuote = true;
                    continue;
                } else if ( c == '/' && i + 1 < str.length() && str.charAt(i + 1== '*' ) {
                    isMultiComment = true;
                    continue;
                }
                 
                // 괄호 체크
                BracketType type = BracketType.getType(c);
                
                if (type != null) {
                    if (!brackets.isEmpty() && brackets.peek().checkBracket(type)) {
                        brackets.pop();
                    } else {
                        brackets.push(type);
                    }
                }
            }
        }
        
        return brackets.isEmpty();
    }
    
    /**
     * 텍스트 읽기
     * 
     * @param fileName
     * @param list
     * @throws IOException
     */
    public static void readText(String fileName, List<String> list) {
        try (FileChannel fileChannel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            
            Charset charset = Charset.defaultCharset();
            int byteCount;
            
            while (true) {
                byteCount = fileChannel.read(buffer);
                
                if (byteCount == -1)
                    break;
                
                buffer.flip();
                String line = charset.decode(buffer).toString().trim();
                
                if (null == line || line.length() == 0) {
                    continue;
                }
                
                list.add(line);
                buffer.clear();
            }
            fileChannel.close();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
    
}
cs





- 괄호에 대한 종류를 담고 있는 Enum 클래스
- 각 괄호를 나타내는 Enum 객체마다 괄호가 정상적으로 닫히는지 여부를 체크하는 메소드가 재정의 되어있음



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package practice1;
 
/**
 * 문장의 괄호 종류와 체크로직
 * 
 * @author wedul
 *
 */
public enum BracketType implements CheckBracketI {
    BIG_RIGHT_BRACKET('}') {
        @Override
        public boolean checkBracket(BracketType type) {
            return false;
        }
    },
    SMALL_RIGHT_BRACKET(')') {
        @Override
        public boolean checkBracket(BracketType type) {
            return false;
        }
    },
    SMALL_LEFT_BRACKET('(') {
        @Override
        public boolean checkBracket(BracketType type) {
            return type.equals(SMALL_RIGHT_BRACKET);
        }
    },
    BIG_LEFT_BRACKET('{') {
        @Override
        public boolean checkBracket(BracketType type) {
            return type.equals(BIG_RIGHT_BRACKET);
        }
    },
    MIDDLE_LEFT_BRACKET('[') {
        @Override
        public boolean checkBracket(BracketType type) {
            return type.equals(MIDDLE_RIGHT_BRACKET);
        }
    },
    MIDDLE_RIGHT_BRACKET(']') {
        @Override
        public boolean checkBracket(BracketType type) {
            return false;
        }
    };;
    ;
    
    private char data;
    
    private BracketType(char data) {
        this.data = data;
    }
    
    public char getData() {
        return this.data;
    }
    
    /**
     * getType
     * 
     * @param input
     * @return
     */
    public static BracketType getType(char input) {
        for (BracketType type : values()) {
            if (type.getData() == input) {
                return type;
            }
        }
        
        return null;
    }
}
cs




- enum에서 사용된 인터페이스


1
2
3
4
5
6
7
8
9
10
11
12
13
package practice1;
 
/**
 * 괄호의 종류별로 체크하는 메소드를 포함한 인터페이스
 * 
 * @author wedul
 *
 */
public interface CheckBracketI {
    
    boolean checkBracket(BracketType type);
 
}
cs



결과




테스트 파일


paren1.txt

paren2.txt

paren3.txt



댓글()

Stack - 후위 표기법으로 된 식 계산

IT 지식/자료구조|2018. 5. 27. 21:01

1 3 + 4 * 와 같이 후위 표기되어있는 식을 계산하는 프로그램을 stack을 이용해서 만들어라

주의사항
- 피연산자가 너무 많으면 오류를 발생시켜라.
- 피연산자가 적어도 오류를 발생시켜라
- 연산자가 사칙연산 이외의 것이 나오면 예외를 발생시켜라
- 결과는 소수점 둘째까지 반올림해서 표현하라.
- 예외는 이 프로그램을 위한 예외를 새로 만들어라

구성
- 파일을 읽는 메서드가 담긴 util 클래스
- 동작이 진행되는 Main 클래스
- 이 프로그램의 예외 OperatorException 클래스



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package practice2;
 
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.List;
 
/**
 * 유틸 클래
 * 
 * @author jeongcheol
 *
 */
public class UtilClass {
    
    /**
     * 텍스트 파일을 읽어서 List에 삽입 
     * 
     * @param fileName
     * @param list
     */
    public static void readText(String fileName, List<String> list) {
        try (FileChannel fileChannel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            
            Charset charset = Charset.defaultCharset();
            int byteCount;
            
            while (true) {
                byteCount = fileChannel.read(buffer);
                
                if (byteCount == -1)
                    break;
                
                buffer.flip();
                String line = charset.decode(buffer).toString().trim();
                
                if (null == line || line.length() == 0) {
                    continue;
                }
                
                list.addAll(Arrays.asList(line.split("\n")));
                buffer.clear();
            }
            fileChannel.close();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
 
}
 
 
package practice2;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
 
import org.apache.commons.lang3.StringUtils;
 
public class Main {
 
    private static final List<String> fileList = Arrays.asList("file/practice1/postfix.txt"  , "file/practice1/postfix1.txt");
    private static final List<String> operator = Arrays.asList("+""-""/""*");
    private static final List<String> readText = new ArrayList<>();
    private static final Stack<String> operand = new Stack<>();
 
    public static void main(String args[]) {
        for (String file : fileList) {
            UtilClass.readText(file, readText);
            readText.stream().forEach(x -> {
                try {
                    process(x);
                } catch (OperatorException e) {
                    System.out.println(e.getMessage());
                }
            });
            readText.clear();
        }
    }
 
    /**
     * 서식 처리 
     * 
     * @param str
     * @throws OperatorException
     */
    private static void process(String str) throws OperatorException {
        // 초기
        operand.clear();
 
        // 빈 문자열 체크
        if (StringUtils.isBlank(str)) {
            return;
        }
 
        for (String ch : str.replaceAll("\\r\\n|\\r|\\n|\\n\\r""").split(" ")) {
            if (StringUtils.isNumeric(ch)) {
                operand.push(ch);
            } else if (operator.contains(ch)) {
                checkOperand();
                
                double operand2 = Double.valueOf(operand.pop());
                double operand1 = Double.valueOf(operand.pop());
                
                switch (ch) {
                case "+":
                    operand.push(String.valueOf(operand1 + operand2));
                    break;
 
                case "-":
                    operand.push(String.valueOf(operand1 - operand2));
                    break;
 
                case "*":
                    operand.push(String.valueOf(operand1 * operand2));
                    break;
 
                case "/":
                    operand.push(String.valueOf(operand1 / operand2));
                    break;
                    
                default:
                    throw new OperatorException("An unsupported operator.\n");
                }
            } else {
                throw new OperatorException(ch + " operator is unsupported operator.\n");
            }
        } 
        
        // 결과 확인
        checkResult();
        
        System.out.printf(" = %.2f\n" ,Double.valueOf(operand.peek()));
        System.out.println();
    }
    
    /**
     * 계산 전 피연산자 개수 체크 
     * 
     * @throws OperatorException
     */
    private static void checkOperand() throws OperatorException {
        if (operand.isEmpty() || operand.size() < 2) {
            throw new OperatorException("Not enough operand.\n");
        }
    }
    
    /**
     * 계산 후 피연산자 개수 체크 
     * 
     * @throws OperatorException
     */
    private static void checkResult() throws OperatorException {
        if (operand.size() != 1) {
            throw new OperatorException("Too many operand.\n");
        }
    }
    
 
}
 
 
package practice2;
 
/**
 * 연산 입센션 추가 
 * 
 * @author jeongcheol
 *
 */
public class OperatorException extends Exception {
 
    private static final long serialVersionUID = 1L;
    
    public OperatorException(String errMsg) {
        super(errMsg);
    }
 
}
cs



결과




postfix.txt

postfix1.txt




댓글()