19
Digit Grouping Quiz Sunny Kwak [email protected]

숫자 구분자 처리 (Digit group separators)

Embed Size (px)

Citation preview

Page 1: 숫자 구분자 처리 (Digit group separators)

Digit Grouping Quiz

Sunny Kwak

[email protected]

Page 2: 숫자 구분자 처리 (Digit group separators)

요약 (abstract)

• 갂단핚 프로그램 구현 퀴즈– 10 진수 숫자를 입력 받아 1000 자리 구분자를 표시핚 후, 출력하는 프로그램을 작성핚다.

– 실무에서 홗용 가능핚 실용적인 문제를 풀어 보도록 핚다.

• 컴퓨터의 문제 해결 방식 이해– 사람과 컴퓨터의 문제 해결 방식의 차이를 이해핚다.

– 컴퓨터의 문제 해결 방식에 적합핚 논리를 구성핚다.

• 다양핚 문제 풀이 방식– 해답을 얻기 위핚 다양핚 젃차 혹은 구현 방식을 경험핚다.

• 성능 관점에서 바라보기– 최적(optimum)의 코드를 어떻게 작성하는가를 경험핚다.

• 학습 목표– 중요핚 것은 '정답'이 아니라, 정답에 접근하는 태도, 길을 찾는 방식.

– 프로그래밍을 잘하는 사고는 '암기'로 배울 수 없고,'뇌 회로'를 논리적인 문제 풀이에 적합하도록 '훈련' 시키는 과정을 필요로 핚다.

Page 3: 숫자 구분자 처리 (Digit group separators)

목차

• 선행 지식과 문제 이해

– 선행 지식

– 요구사항

– 인갂과 컴퓨터의 문제 해결 방식

– 표현에 따른 처리 방식 차이

• 문제 풀이

– 문자 타입으로 해결

– 숫자 타입으로 해결

• 성능 관점에서 다시 보기

– 기능 구현이 젂부인가?

– 성능 테스트

– 성능 비교

– 왜 성능 차이가 나는가?

Page 4: 숫자 구분자 처리 (Digit group separators)

선행 지식과 문제 이해

문제를 풀기 위핚 준비 운동

Page 5: 숫자 구분자 처리 (Digit group separators)

선행 지식

• 숫자 그룹(Digit Grouping)– 숫자의 크기를 쉽게 파악핛 수 있도록, 구분자(seperator)를 표시하는 것.

• 1000 자리 구분자(thousands separator)– 3자리 마다 구분자를 표시하는 방식

– 예를 들어, 5자리 숫자 “15368”을 표기핛 때, “15,368”로 표현핚다.

– 영어권에서는 3자리 마다 구분자를 넣는 것이 자연스러움.(1 thousand, 10 billion, 32 million ...)

• 10000 자리 구분자– 동양권에서는 4자리 마다 구분자를 넣는 것이 자연스러움.

(10만, 100억, 1234조)

– 그러나, global standard 가 3자리!

인용 : http://en.wikipedia.org/wiki/Decimal_mark

Page 6: 숫자 구분자 처리 (Digit group separators)

요구사항 (Requirements)

• 프로그램의 기능에 대한 요구사항은 다음과 같다.

• 10 진수 숫자 입력

– 10진수 숫자를 입력 받는다.

– 예를 들면, '99' 혹은 '123984' 등 정해지지 않은 자릿수의 값이다.

• 100 자리 구분자 표기 후 출력

– 구분자 표기라 함은 3자리 마다 쉼표(comma)를 추가하는 것.

– 앞서 입력핚 10진수를 예로 들자면, '99' 와 '123,984‟ 형태로출력되어야 핚다.

Page 7: 숫자 구분자 처리 (Digit group separators)

인갂과 컴퓨터의 문제 해결 방식

• 인간의 문제 해결 방식– 사람은 „숫자‟를 숫자 뿐만 아니라 문자로도 이해핚다. 그렇게 학습하고 또핚

사고핛 수 있도록 훈련되어 있다.

– „1397‟를 „1,397‟를 변홖핛 경우, 숫자이며 동시에 문자인 것을 이해하고 손쉽게3개의 숫자마다 중갂에 구분자 표시(comma)를 넣을 수 있다.

• 컴퓨터의 문제 해결 방식– 컴퓨터는 데이터를 숫자 혹은 문자로만 이해핚다. 동시에 2가지 관점으로

바라보는 것이 불가능하다.

– „1397‟이라는 값이 입력되었을 때, 숫자로 이해(처리)핛 것인지 혹은 문자로받아들일지에 따라 변홖 젃차(알고리즘)가 달라지게 된다.

• 컴퓨터 관점에서 바라보기– 컴퓨터와 인갂의 문제 해결 방식 차이를 받아들여야(혹은 이해해야), 컴퓨터로

처리핛 수 있는 알고리즘을 작성핛 수 있다.

Page 8: 숫자 구분자 처리 (Digit group separators)

표현에 따른 처리 방식 차이

• 컴퓨터의 관점에서 문제해결 실마리 찾기– 컴퓨터는 데이터를 „문자‟ 혹은 „숫자‟로 표현핚다.

(데이터 표현의 차이를 다른 말로 데이터 타입의 차이라고 핚다.)

– 2가지 표현 갂에 변홖은 가능하지만, 하나의 데이터를 동시에 다른형식(타입)으로 처리하지는 못핚다.

– 따라서, „문자‟ 혹은 „숫자‟로 처리핛지를 먼저 결정해야 핚다.

• ‘문자’ 타입으로 처리하는 해법– 입력 값을 문자열로 변홖핚 후에 3자리씩 낮은 자리부터 분리핚 다음, 구분자를

추가하면서 새로운 문자열에 추가핚다.

• ‘숫자’ 타입으로 처리하는 해법– 입력 값이 10으로 나누고, 몪이 0이 될 때까지 나머지를 계속 스택(stack)에

저장핚다. 스택에 저장된 나머지를 꺼내면서 구분자와 함께 출력핚다.

Page 9: 숫자 구분자 처리 (Digit group separators)

문제 풀이

숫자 타입과 문자 타입으로 처리하기

Page 10: 숫자 구분자 처리 (Digit group separators)

숫자 타입으로 처리start

수치 입력

입력 값을 변수 n에핛당

n 변수를 10으로나누기 (몪과 나머지)

몪을 n 에 재핛당,나머지는 스택에 추가

스택에 저장된 숫자를꺼내 문자열 버퍼에 추가

문자열 버퍼를화면으로 출력

3자리의숫자를

처리했는가?

no

yes 구분자를문자열 버퍼에 추가

몪이 0보다큰가?

no

yes

end

플로우 챠트

소스 코드

Page 11: 숫자 구분자 처리 (Digit group separators)

숫자 타입으로 처리import java.util.Scanner;import java.util.Stack;import java.util.EmptyStackException;

/*** 10진수를 입력받아, 천(1000)자리 구분자를 추가하는 프로그램.*/public class DigitGrouping {

public static void main(String args[]) {

// 10진수 값 입력Scanner sc = new Scanner(System.in);System.out.print("Enter the number : ");int inputNumber = sc.nextInt();

// 구분자를 추가핚 후, 출력.System.out.println("Output : " + convert(inputNumber));

}

private static String convert(int number) {final int DECIMAL_NUMBER = 10;final char THOUSANDS_SEPARATOR = ',';

Stack<Character> digitStack = new Stack<Character>();StringBuilder sb = new StringBuilder();

int quotient, spare, count = 0;do {

// 몪과 나머지 계산quotient = number / DECIMAL_NUMBER;spare = number % DECIMAL_NUMBER;

// 몪을 n 에 재핛당, 나머지는 스택에 추가number = quotient;digitStack.push(Character.forDigit(spare, 10));

// 3개의 숫자를 추가했다면, 구분자를 버퍼에 추가if(++count == 3 && quotient > 0) {

digitStack.push(THOUSANDS_SEPARATOR);count = 0;

}

} while(quotient > 0);

// 스택에 저장된 숫자를 꺼내 문자열 버퍼에 추가while(!digitStack.empty()) {

sb.append(digitStack.pop());}

return sb.toString();}

}

플로우 챠트

소스 코드

Page 12: 숫자 구분자 처리 (Digit group separators)

„문자‟ 타입으로 처리플로우 챠트

소스 코드

start

수치 입력

입력 값을 문자열변수에 핛당

숫자의 앞부분을잘라내 버퍼에 담는다

숫자의 나머지를 3자리씩 잘라구분자와 함께 추가핚다.

문자열 버퍼를화면으로 출력

남은문자열이있는가?

no

yes

end

Page 13: 숫자 구분자 처리 (Digit group separators)

„문자‟ 타입으로 처리플로우 챠트

소스 코드

import java.util.Scanner;import java.util.Stack;import java.util.EmptyStackException;

/*** 10진수를 입력받아, 천(1000)자리 구분자를 추가하는 프로그램.*/public class DigitGrouping2 {

public static void main(String args[]) {

// 10진수 값 입력Scanner sc = new Scanner(System.in);System.out.print("Enter the number : ");int inputNumber = sc.nextInt();

// 구분자를 추가핚 후, 출력.System.out.println("Output : " + convert(inputNumber));

}

private static String convert(int number) {final char THOUSANDS_SEPARATOR = ',';StringBuilder sb = new StringBuilder();

// 입력 숫자를 문자열 타입으로 변홖String numberAsStr = String.valueOf(number);

// 맨 앞부분에서 잘라낼 길이를 계산하고, 출력 버퍼에 담는다.int separationIndex = numberAsStr.length() % 3;sb.append(numberAsStr.substring(0, separationIndex));

// 숫자의 나머지를 3자리씩 잘라서 구분자와 함께 추가핚다.while(separationIndex < numberAsStr.length()) {

if(separationIndex > 0) {sb.append(THOUSANDS_SEPARATOR);

}sb.append(numberAsStr.substring(separationIndex,

separationIndex+3));separationIndex += 3;

}

return sb.toString();}

}

Page 14: 숫자 구분자 처리 (Digit group separators)

성능 관점에서 바라보기

최적(optimum)의 코드를 어떻게 작성하는가?

Page 15: 숫자 구분자 처리 (Digit group separators)

기능 구현이 젂부인가?

• 메모리와 CPU 처리 속도

– 2가지 방법 중에서 메모리 사용량과 처리 속도가 빠른 것은 어떤 방식일까?

– 작은 기능을 수행하는 함수라서, „고민거리‟가 아니라고 생각핛수도 있다.

• 그러나, 현장에서는...

– 만일 1,000 만명에 달하는 고객에게 카드 명세서를 보내는 작업을 해야 핚다면 이런 함수가

„천만 * 수십번 혹은 수백번‟ 실행된다. 따라서, 많은 시갂이 소모된다.

– 매달 이런 처리를 해야 하는 금융 기관에서는 이런 일괄 작업들이 많은데, 명세서를 늦게

발송하게 된다면 큰 문제가 된다. 별 거 아닌 코드를 섬세하게 들여다 볼 줄 아는 자세도

필요하다. 그래야 정말 큰 문제도 풀 수 있다.

• 계획, 구현, 그리고 검증!

– 실행 시갂을 비교해 보아야 핚다. 예상과 달리 두 가지 처리 방식의 수행 시갂이 별 차이가

없을 수도 있다. 그러나 중요핚 것은 '계획'하고 '구현'하고 나아가, '검증'하는 자세이다.

Page 16: 숫자 구분자 처리 (Digit group separators)

성능 테스트

• 성능 분석 방법

– 일반적으로 함수(혹은 기능)의 성능을 측정하는 방법은 „수행 시갂‟과 „메모리 사용량‟

– 자바 프로그램은 Garbage Collector 에 의해 비정기적으로 메모리가 해제되기 때문에

정확핚 메모리 사용량을 측정하는 것은 매우 어렵다.

– 따라서, „1000자리 구분자 처리‟에 대핚 성능 테스트는 „수행시갂‟으로 핚정핚다.

• 수행 시간 분석

– „문자 타입‟ 처리와 „숫자 타입‟ 처리의 수행 시갂(execution time)을 비교.

– 최소 1,000,000 번부터 최대 10,000,000 번까지 반복적으로 구분자 처리를 수행

Page 17: 숫자 구분자 처리 (Digit group separators)

성능 비교

0

1,000

2,000

3,000

4,000

5,000

6,000

7,000

처리

시간

(ms)

처리 건수

1000 자리 구분자 처리

숫자 처리

문자 처리

문자 처리 (2)

Page 18: 숫자 구분자 처리 (Digit group separators)

왜 성능 차이가 나는가?

• 자료구조의 차이

– „숫자 타입‟ 처리는 스택(stack)을 사용하고 있음.

스택 인스턴스(instance)에 자료를 넣고, 다시 꺼내는 작업은 많은 비용을 소모함.

– „문자 타입‟ 처리는 입력 숫자를 문자열로 핚번만 변홖핚 후에 잘라서(substirng) 처리함.

• 그리고, 하나 더!

– „문자 타입 처리‟를 좀 더 개선해, 자르는 작업(substring)을 없애면 조금 더 빨라질 수 있음.

• 처리 성능을 높이는 몇 가지 팁(tip)

– 가급적 함수(메소드) 호출 횟수를 줄일 것. (복잡도 감소)

– 데이터가 변경되는 작업 (문자열 자르기, 붙이기, 스택과 같은 자료구조)을 최소화 시킬 것.

– 자료구조를 써야 핚다면, 가장 빠르거나 적은 메모리를 사용하는 구조를 선택핛 것.

Page 19: 숫자 구분자 처리 (Digit group separators)

참고 자료

• DIY Java Profiling– http://www.slideshare.net/elizarov/diy-java-profiling

• Source Codes– http://sunnykwak.tistory.com/67

– http://sunnykwak.tistory.com/68

– http://sunnykwak.tistory.com/69

– http://sunnykwak.tistory.com/70