2013년 12월 31일 화요일

java 정규식에서 많이 사용하는 항목들(개인적으로...)

블로그에 글을 기재하기 시작한지 얼마 되지 않지만, 처음과는 다른각도에서 접근하게 되는것 같습니다.

개인적인 정리가 필요해서 시작했고, 지금도 그것이 중요한 이유이지만, 간혹 드물게 접속해서 보시는 분들이 있는 것 같습니다.
제가 검색등을 통해서 도움을 받았듯, 혹시라도 조금이라도 도움이 될 수 있다면 좋겠다는 생각을 아주 가끔(^^)은 하게 되었습니다.
조금은 생각을 정리해서 기재 해야 겠다는 생각이 들기 시작하는 중입니다. 

정규식은 Java 아닌 다른 곳에서도 많이 사용되는 표현 형식입니다.   
문장중의 특정 단어를 찾거나, 일부분을 변경하는 것 등에서도 많이 사용됩니다.  Linux 등의 환경에서는 일반정규식은 말할 것도 없고, 정규식이라 말하긴 어려워도 검색(파일 및 내용)을 위한 많은 명령어가 제공되기도 합니다. (awk, sed 등의 명령어는 정말 강력합니다. find 와 함께 쓰는 xargs 명령어도 파일 내용을 찾는 데에는 더할 나위 없이 강력하고요 ... ), Unix 에서의 egrep 는 정규식 사용할 수 있게 도와 줍니다.

java 에서는 java.util.regex package 정규식 관련한 내용이 담겨 있습니다.
처음 블로그 할 때 기록했던 수치 확인 내용을 다시 한번 기록해 보겠습니다.
[+\\-]?([\\d]+([.][\\d]*)?|[.][\\d]+)([eE][+\\-]?[\\d]+)? 
숫자형으로 넘어온 데이터가 DB 에서 문자열로 가져올 때, 가끔 형변환된 문자열이 다음과 같이 출력되어 나타날 수가 있습니다. -.7265  -1.2E+12 등의 문자열에서 -.으로 -0.7.. 형식이 아닌 데이터가 나타날 때도 수치형 데이터 라고 인식 시켜 주려면 +,- 기호가 사용가능한 
기호라는 표기가 필요합니다. 그게 [+\\-]? 기호 입니다. \\기호는 - 기호가 [] 블럭에서 이미 사용되고 있는 문자열이라서 의미 자체로 '-' 다 라는 것을 인식시켜 주기 위한 부분 입니다.  '?' 는 있을 수도 있고 없을 수도 있다라는 의미로 받아 들이시면 됩니다. 
정규식 API 를 참조하시면서 보시면 쉽게 확인 하실 수 있을 것 같습니다.  참고로 [\\d\\w]+ 라는 의미는 숫자 혹은 문자라는 의미 입니다. 

그럼 위의 내용을 어떻게 사용할까요 ?
위의 내용은 굳이 Patten 객체까지 사용하지 않고 String 객체에서 직접 사용하 실 수 있습니다.   아래와 같은 간단한 코드 입니다.
public static boolean isNumberFormatStr(String str) {
if ( str == null ){
return false;
}
return str.matches("[+\\-]?([\\d]+([.][\\d]*)?|[.][\\d]+)([eE][+\\-]?[\\d]+)?");
}

다음의 코드를 살펴보겠습니다.

public static void testRegex() {
StringBuffer sb = new StringBuffer();
sb.append("<a href=\"www.google.co.kr\" \r\n target=\"_black\"> TEST </a><a onClick=www.naver.com> test2\r\n</a>");

System.out.println( sb );

Pattern pObj = Pattern.compile("(<[^>]*>)",Pattern.MULTILINE);
Matcher mObj = pObj.matcher(sb);
while ( mObj.find()) {
System.out.println (mObj.groupCount() + " : " + mObj.group(0));
}

pObj = Pattern.compile("(<(/)?([\\w]+)([\\s]+[^>]*)?>)",Pattern.MULTILINE);
mObj = pObj.matcher(sb);
while ( mObj.find()) {
int cnt = mObj.groupCount();
for ( int i = 1; i <= cnt; i++ ) {
System.out.print ("\t\t" + i + " : " +  mObj.group(i));
}
}
}

html tag 를 확인하기 위한 코드 입니다.
처음에는 단순히 tag 만을 확인 하기 위해서 '<'가 있고 '>' 이 아닌 모든것인 있을 수도 있고 '>' 이 있는 유형을 찾도록 했습니다. <[^>]*> 가 그런 의미 입니다.
하지만 이렇게 되면 tag 안의 내용을 다시 확인하여야 합니다. 종료 tag인지 아닌지 이름이 뭔지 속성은 있는지 등등을요 그래서 (/)? 으로 종료 태그 여부를 확인합니다. 다시 태그 이름은 '<'다음에 붙어 나오는 단어이기 때문에 [\\w]+로 확인을 합니다.
그 다음은 속성에 해당하는 것이 있다면  확인하는 구문이 들어 있습니다.
()기호와 []기호 + ? * {1,5} 등의 기호로 찾아야할 영역을 지정할 수 있습니다.

아래의 내용을 한번 살펴 보겠습니다.
"ABCDEFGABCDEFGABCDEFG ABCDEFGABCDEFGABCDEFG" 라는 문장이 있습니다.
이 문장에서 EFG 가 포함된 영역과 그 외 영역을 찾고자 한다고 가정해 보겠습니다.
일반적으로 생각해 볼 수 있는 정규식은 (.+)(EFG)라는 문장을 생각해 볼 수 있습니다.
무엇이 되었던 EFG 앞의 내용은 다 그리고 EFG 를 찾아라 하는 구성입니다.
이것을 실행하면 ABCDEFGABCDEFGABCDEFG ABCDEFGABCDEFGABCD EFG 의 두 영역을 찾아 오게 됩니다.  원하는 내용이었다면 다행이지만 의도가 ABCD EFG 의 반복을 원하였다면 위의 정규식에서 (.+?)(EFG)의 구성으로 변경해 주시면 됩니다. +뒤의 ? 의 의미는 EFG 가 포함된 영역을 최소한의 수준에서 찾아 주게 됩니다.
API의 Greedy quantifiers, Reluctant quantifies 의 내용을 확인해 보시면 됩니다.
문장 전체에서 특정 영역을 찾아 오는 Parser를 구성할 때 위의 내용이 빈번하게 사용될 수 있습니다.(제 개인적으론 그렇습니다.)
코드로 구성해 보면 다음과 같습니다.

String str = "ABCDEFGABCDEFGABCDEFG ABCDEFGABCDEFGABCDEFG";
System.out.println ("\n\n" + str );
Pattern pObj = Pattern.compile("(.+?)(efg)",Pattern.CASE_INSENSITIVE);
Matcher mObj = pObj.matcher(str);
while ( mObj.find() ) {
System.out.println (mObj.group(1) + " : " + mObj.group(2) );
}


정규식은 mail 형식 html tag 수치확인 등의 단순한 확인 및 처리에서 부터 좀더 복잡한 파일내용의 분석 등 다양한 영역에서 사용할 수 있습니다.  정규식의 강력함을 접하면서 다 알지는 못하지만, 혹시 정규식을 많이 접하지 않았던 분들에게 조금이라도 도움이 될 까 해서 기록해 보았습니다.






2013년 12월 11일 수요일

R Graph를 이용한 금융계산

R은 통계 툴입니다.
주어진 데이터를 분석 추정하는데 사용하는 강력한 툴입니다.

그렇지만 생활에서 많이 접하는 정기예금, 단리, 복리 수익 및 대출등의 금융계산에 이용할 수도 있습니다.

R의 그래프 기능을 이용하여 아주 간단한 R 프로그램을 구성해 보겠습니다.

먼저 간단한 예로 일정금액을 일정기간동안 예치해 놓는 경우를 가정해 보겠습니다.  기간동안 이자가 발생하는데 첫번째는 금액의 이자가 단순히 기간에 비례하여 증가하는 경우(경우1)와 금액의 이자가 합산되어 증가되는 경우(경우2)를 가정해 보겠습니다.

amount 는 원금입니다.
period는 연단위 기간입니다.
rate는 연단위 이자 입니다.   이자는 월단위로 발생하는 것으로 가정하겠습니다.

경우1)
fnSimple <- function(amount,period,rate) { amount*period*rate + amount }

경우2)
fnCompound <- function(amount,period,rate) { amount*(1+rate/12)^(period*12) }

이제 조건을 정해 보겠습니다.
두 영역의 차이를 크게 하기 위해 기간과 이율을 좀 높혀서 확인해 보겠습니다.
amt 는 원금 입니다. (원 단위 만원단위는 편하게 생각하셔도 됩니다.)
px 는 기간 입니다. 1년에서 100년 까지 설정한 것입니다.
rt 는 이율 입니다.
amt <- 1000;  px <- c(1:100);  rt <- 0.12;
psy <- fnSimple(amt,px,rt)
pcy <- fnCompound(amt,px,rt)
plot(px,pcy,type='o',col='blue',tck=1);
points(px,psy,type='o',col='red');
위의 내용을 보시면 다음과 같습니다.


그래서 y축의 값을 로그로 환산하여 처리해 보았습니다.
plot(px,pcy,type='o',col='blue',log='y',tck=1);
points(px,psy,type='o',col='red');



이제 매월 일정액을 납부하여 만기일에 이자와 원금을 받는 경우를 가정해 보겠습니다.  세금납부는 제외하겠습니다.
먼저 단리의 경우입니다.  단리는 납부원금에 대해서만 발생하는데 매월 일정액이 납부되기때문에 일정한 값만큼 증가하게 됩니다. 예를 들어 10만원에 월 1% 이자 (연 12%)라면. 첫달에 1000원 둘째달에 2000원(200000×0.01) , 셋째달은 3000원이 발생합니다.
등차수열의 합을 구하는 방식을 연상해 보시면 됩니다.  (초항+마지막항)×기간/2 가 이자금액의 합이됩니다.
fnMSimple <- function(amount,period,rate) { rateM <- rate/12; (amount*rateM+amount*rateM*period*12)*period*12/2 + amount*period*12 }

복리는 원금에 이자가 합산되어 이자가 발생하는 방식입니다.
첫달은 원금*연이률/12+원금 입니다. 식으로 표현하면 amount*(1+rate/12) 입니다.
둘째달은 (첫째달 금액 + amount)*(1+rate/12) 입니다. 결국 등비수열의 합 공식으로 유도됩니다.
fnMCompound <- function(amount,period,rate) { rateM <- rate/12; amount*(1+rateM)*((1+rateM)^(period*12)-1)/(rateM) }

100년의 기간은 너무 많은 차이를 나타내기 때문에 이곳에서 20년 정도로 기간을 단축해 보겠습니다.   그리고 금액도 10 정도를 매달 저금하는 것으로 해 보겠습니다.

amt <- 10; px <- c(1:20);
psy <- fnMSimple(amt,px,rt);
pcy <- fnMCompound(amt,px,rt);
plot(px,pcy,type='o',col='blue',tck=1);
points(px,psy,type='o',col='red');
points(px,px*amt*12,type='o');




10년 정도의 기간에서는 큰 차이가 발생하지 않지만 20년 정도에는 2배 가량 차이가 나타나고 있습니다.


대출의 경우는 대개 2가지 방식으로 진행 될 수 있습니다.
매달 원금에서 동일한 금액을 상환하는 방식(원금균등상환)과 매달 동일한 금액을 상환하는 원리금균등상환 방식을 생각해 볼 수 있습니다.
전자(원금균등)의 방식이 총액에서는 이익이지만 초기에 상환해야할 금액이 커질 수 있습니다.
아래는 함수 입니다. 상환이기 때문에 기간은 월단위로 설정해 보겠습니다.

fnSLoan <- function(amount,period,rate) {
    result <- c(1:period);
    mAmt <- amount/period;
    mRate <- rate/12;
    for ( i in c(1:period) ) {
        result[i] <- amount*mRate+mAmt;
        amount <- amount-mAmt;
    }
    result;
}

fnCCalc <- function(amount,period,rate) { (amount*rate/12*(1+rate/12)^period)/((1+rate/12)^period-1) }

fnCRemain <- function(amount,period,rate,mAmt) {
    result <- c(1:period);
    mRate <- rate/12;
    for ( i in c(1:period) ) {
        mAmtR <- mAmt-amount*mRate;
        amount <- amount-mAmtR;
        result[i] <- amount
    }
    result;
}


2013년 12월 9일 월요일

R 설치 및 간략한 소개

R은 프로젝트에서 사용해 보고는 바로 매료되었던 통계 관련툴입니다.
무엇보다도 open source로 개발되어 배포되는 무료 툴입니다.  이런 모듈을 사용하다 보면 외국의 IT 환경이 부럽기도 하고, 부끄러움도 느끼게 되는것 같습니다.

통계 전반을 사용하지는 못하였고, 그 기능 중 일부분인 Graph 기능을 중심으로 사용해 보았습니다.

Windows에는 설치 파일을 실행하는 것으로 거의 모든 과정이 종료 되기 때문에 간단하게 설치할 수 있습니다.

다음의 사이트를 참조하여 파일과 내용을 확인하실 수 있습니다.
http://www.r-project.org/

windows 환경에서는 설치와 동시에 메뉴에서 마우스 클릭으로 접근할 수 있습니다.(설치시 기본으로 하셨다면)
console 에서 사용하고 싶으시다면, path를 잡아 주셔야 합니다.(그래야 사용하기 편합니다.)

cmd 창에서 R 이라고 입력하고 enter를 클릭하면(Path가 잡혀 있을 경우) > 표시가 표현되면서 명령어 입력 창이 나타 납니다.

종료하려면 quit()를 입력하고 enter를 클릭하시면 됩니다.

사용법은 매뉴얼을 참조하시면 되지만, 이 글에서는 그래프중 perspective Plots 을 예제로 기록하겠습니다.

> ?persp 를 입력하고 enter를 클릭하면 새로운 webpage가 구동하면서 상세 내용이 뜨게 됩니다. ?(keyword)로 해당 내용을 확인하실 수 있습니다.
내용중 예제에 나와 있는 부분을 복사해 보았습니다.

x <- seq(-10, 10, length= 30)
y <- x
f <- function(x, y) { r <- sqrt(x^2+y^2); 10 * sin(r)/r }
z <- outer(x, y, f)
z[is.na(z)] <- 1
op <- par(bg = "white")
persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue")
persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue",
      ltheta = 120, shade = 0.75, ticktype = "detailed",
      xlab = "X", ylab = "Y", zlab = "Sinc( r )"
) -> res
round(res, 3)

아래는 그 결과 이미지 입니다.
<- 또는 -> 등은 방향을 가진 할당 (다른 언어의 '=' 해당) 기능을 가지고 있습니다.
변수 선언이 형없이 선언되고 있습니다.  (어떤 면에서는 javascript 와 유사한 문법 구조를 가지고 있습니다.)

그래프에서 대표적인 것은 plot 이지만, 위의 그래프는 직접 구현할 때 많은 노력이 들어가야할 graph 유형까지 지원하고 있는 것을 보여 주는 예인것 같아서 예시해 보았습니다.