카테고리 보관물: 프로그래밍

프로그래밍에 관련된 여러가지 정보

Mean, RMS and Covariance with computer

데이타 처리를 하면서 평균과 표준편차를 구해야 하는 경우가 많이 있다. 이 때, 평균과 표준편차의 계산을 점화식을 이용해서 하면 반복문의 수를 반으로 줄여서 빠르게 계산을 할 수 있다.

  • 증명따윈 필요없는 귀차니스트를 위한 식

평균: \(\mu_{n+1} = \displaystyle\frac{n}{n+1}\mu_n + \displaystyle\frac{a_{n+1}}{n+1},\quad(n\geq0). \)

표준편차: \(\sigma^2_{n+1}=\displaystyle\frac{n}{n+1}\sigma^2_{n}+\displaystyle\frac{(\mu_{n+1}-a_{n+1})^2}{n},\quad(n\geq1).\)

공변: \(\sigma(a,b)_{n+1}=\displaystyle\frac{n}{n+1}\sigma(a,b)_{n}+\displaystyle\frac{(\mu_{n+1}-a_{n+1})(\nu_{n+1}-b_{n+1})}{n},\quad(n\geq1).\)

  • 평균 증명
    • 점화식을 이용해서 \(n+1\)번째 항까지의 평균을 구할 때 우리가 가지고 있는 정보는 다음과 같다.
      1. \(n\)번째 항까지의 평균 \(\mu_n\)
      2. \(n+1\)번째 항의 값 \(a_{n+1}\)
    • 이 정보들만 가지고 \(n+1\)번째 항까지의 평균을 구해내야 한다.

\[\begin{align}\mu_{n+1}&=\displaystyle\sum^{n+1}_{i=1}\displaystyle\frac{a_i}{n+1},\\&=\displaystyle\sum^{n}_{i=1}\displaystyle\frac{a_i}{n+1}+\displaystyle\frac{a_{n+1}}{n+1},\\&=\displaystyle\frac{a_{n+1}}{n+1}+\displaystyle\frac{n}{n+1}\displaystyle\sum^{n}_{i=1}\displaystyle\frac{a_i}{n}.\end{align}\]

\[\therefore \mu_{n+1}=\dfrac{n}{n+1}\mu_n+\dfrac{a_{n+1}}{n+1},\quad(n\geq0).\]

 

  • 표준편차 증명
    • \(n+1\)번째 항까지의 표준편차를 구할 때에 우리가 가지고 있는 정보는 다음과 같다.
      1. \(n\)번째 항까지의 표준편차 \(\sigma^2_{n}\)
      2. \(n+1\)번째 항까지의 평균 \(\mu_{n+1}\)
      3. \(n+1\)번째 항의 값 \(a_{n+1}\)
    • 평균과 마찬가지로, 표준편차를 구할 때도 위 세 가지 값만 가지고 \(n+1\)번째 항까지의 표준편차를 구해야 한다.

\[\begin{align}\sigma^2_{n+1}&=\sum^{n+1}_{i=1}\dfrac{(a_i-\mu_{n+1})^2}{n+1},\\&=\sum^{n}_{i=1}\dfrac{(a_i-\mu_{n+1})^2}{n+1}+\frac{(a_{n+1}-\mu_{n+1})^2}{n+1}.\qquad (1)\end{align}\]

두번째 항은 알고있는 값들로만 돼 있으니 놔두고, 첫번째 항을 알고있는 값들로만 바꿔주면 된다.

\[\begin{align}\sum^{n}_{i=1}(a_i-\mu_{n+1})^2-\sum^{n}_{i=1}(a_i-\mu_n)^2&=\sum^{n}_{i=1}(\mu_n-\mu_{n+1})(2a_i-\mu_{n+1}-\mu_n),\\&=(\mu_n-\mu_{n+1})(2n\mu_n-n\mu_{n+1}-n\mu_n),\\&=n(\mu_{n+1}-\mu_n)^2.\qquad(2)\end{align}\]

이제 식 (2)를 식 (1)에 넣어 정리하면,

\[\begin{align}\sigma^2_{n+1}&=\sum^{n}_{i=1}\dfrac{(a_i-\mu_n)^2}{n+1}+\dfrac{n}{n+1}(\mu_{n+1}-\mu_n)^2+\dfrac{(a_{n+1}-\mu_{n+1})^2}{n+1},\\&=\dfrac{n}{n+1}\sigma^2_{n}+\dfrac{n}{n+1}(\mu_{n+1}-\mu_n)^2+\dfrac{(a_{n+1}-\mu_{n+1})^2}{n+1}.\qquad(3)\end{align}\]

\(n\)번째 항까지의 평균값은 \(n+1\)번째 항까지의 평균값을 구하면서 없어졌으므로, 평균의 점화식 공식을 이용해서 \(n\)번째 항까지의 평균값을 없애버리자. 점화식을 다시 정리하면

\[\mu_n=\dfrac{n+1}{n}\mu_{n+1}-\dfrac{1}{n}a_{n+1}\]

가 되므로, 이 식을 식 (3)의 두번째 항에 대입하면, 두번째 항은 다음과 같이 된다.

\[\begin{align}\dfrac{n}{n+1}(\mu_{n+1}-\mu_n)^2&=\dfrac{n}{n+1}\left(\mu_{n+1}-\dfrac{n+1}{n}\mu_{n+1}+\dfrac{1}{n}a_{n+1}\right)^2,\\&=\dfrac{1}{n(n+1)}(a_{n+1}-\mu_{n+1})^2\end{align}\]

\[\therefore \sigma^2_{n+1}=\dfrac{n}{n+1}\sigma^2_{n}+\dfrac{(\mu_{n+1}-a_{n+1})^2}{n},\quad(n\geq1).\]

  • 공변 증명은 표준편차 증명과 똑같은 방식이므로 생략한다.
  • 각 값의 가중치가 같지 않을 때의 평균과  공변 식

평균: \(\mu_{n+1} = \displaystyle\frac{W_n}{W_n+w_{n+1}}\mu_n + \displaystyle\frac{w_{n+1}a_{n+1}}{W_n+w_{n+1}},\quad(n\geq0). \)

표준편차: \(\sigma^2_{n+1}=\displaystyle\frac{W_n}{W_n+w_{n+1}}\sigma^2_{n}+\displaystyle\frac{w_{n+1}(\mu_{n+1}-a_{n+1})^2}{W_n},\quad(n\geq1).\)

공변: \(\sigma(a,b)_{n+1}=\displaystyle\frac{W_n}{W_n+w_{n+1}}\sigma(a,b)_{n}+\displaystyle\frac{w_{n+1}(\mu_{n+1}-a_{n+1})(\nu_{n+1}-b_{n+1})}{W_n},\quad(n\geq1).\)

위 식들에서 \(W_n=\displaystyle\sum^n_{i=1}w_i\)이고, \(w_n\)은 \(n\)번째 값의 가중치이다.

  • Acknowledgement
    • 이정우님이 가중치가 있을 때의 계산 오류에 대해 지적해 주어 바로고침

Multi-Architecture Compiling

아주 가끔가다 32 bit와 64 bit에서 동시에 사용가능한 라이브러리를 컴파일해야 할 필요가 있다. 이 때에,

  • CFLAGS+=”-arch i386 -arch x86_64″
  • CXXFLAGS+=”-arch i386 -arch x86_64″
  • LDFLAGS+=”-arch i386 -arch x86_64″

위 세개를 컴파일과 링크시에 잘 넣어주면 된다. 물론 make할 때 넣어줘도 된다.

컴파일 중간에

  • -E, -S, -save-temps and -M options are not allowed with multiple -arch flags

이런 에러가 난다면, configure 시에

  • –disable-dependency-tracking

옵션을 추가해서 하면 에러가 안난다.

참고:
사실 이게 라이브러리를 벗어나서 실행파일에도 되는지는 확실히 모르겠다. Mac에서 Xcode를 이용해서는 32 bit와 64 bit에서 동시에 사용가능한 바이너리를 만드니까 안될 것 같지는 않지만….

참고문헌

  1. http://blog.omega-prime.co.uk/?p=102

Static, Shared & Dynamic Libraries

내가 이해한대로 적자면, 라이브러리라는건 문자 그대로 “도서관”이라고 보면 된다. A라는 코드에서 B라는 것을 썼는데, B에 대한 정의가 A에 나와있지 않을 때, 다른 라이브러리를 참조해서 B를 가져온다.

이 도서관이 3가지 종류가 있는데, 프로그램을 통째로 이사가 가능한 대학이라고 치면

  • Static Library
    • 도서관이 붙어있는 대학. 대학이 이사갈때마다 도서관도 같이 딸려간다.
  • Shared Library
    • 도서관이 있지만 붙어있진 않은 대학. 대학과 도서관이 독립적으로 존재하지만, 대학 문을 열때마다 도서관 문도 같이 연다.
  • Dynamic Library
    • Shared Library와 대부분 같지만, 대학에서 특별히 요청하지 않는 한 도서관 문을 열지 않는다. 필요할때만 도서관 문을 여는 대학.

참고: Dynamic Library 파일은, 최종본이기 때문에 링킹이 되질 않는다!

참고문헌

  1. http://blog.naver.com/xogml_blog?Redirect=Log&logNo=130138049704

awk & grep

리눅스랑 맥에 기본적으로 깔려있는 awk랑 grep을 이용해서 파일 리스트를 원하는 형태로 조작하는 연습을 하며 이 두 프로그램에 대해 알아보자. 먼저 주어진 리스트는 다음과 같다.

2013-07-20_22-38-44여기서 raw라는 확장자를 가진 파일만 추려서 확장자를 떼고, rawToROOT라는 실행파일의 인자로 넘겨주는 형태로 rawToROOT파일을 실행시키는 문장을 만들려고 한다. 물론 아무생각 없이 ls > run.sh 로 ls 내용을 run.sh에 입력한다음 vi를 이용해서 손으로 하나하나 혹은 매크로로 입력해주는 방법도 있다. 그게 편한 사람은 그걸 그냥 써도 된다. 일단 해보고 생각해보자.

먼저 raw 확장자를 가진 파일만 추려내보자.

ls | grep .raw$

2013-07-20_23-10-47

위 명령어는 ls에서 나온 결과에서 “.raw”로 끝나는 문자를 가진 결과만 출력한다. “$”가 문장의 끝을 의미한다. 결과는 다음과 같다.

이제 이 결과에서 “.raw”확장자를 가진 파일만 추려서 .raw를 떼버리고 앞쪽에 “./rawToROOT ”를 붙이면 완성이다.

ls | grep .raw$ | awk -F.raw ‘{printf(“./rawToROOT %s\n”, $1)}’

2013-07-20_23-11-28끝! awk를 이용해서 “ls | grep .raw$”에서 나온 결과를 편집해서 출력한 것이다. awk의 “-F.raw”옵션은 “.raw”를 기준으로 결과에 있는 문자열을 자른다. 순서대로 자르는 기준의 앞쪽 문자열은 $1에, 뒷쪽 문자열은 $2에 할당된다. 자르는 기준의 문자가 “.”이나 “,”여서 잘리는 위치가 여러군대라면 순서대로 “$숫자”형태로 저장된다. (10 이상까지 되는지는 모르겠다. 한번 해보길….)
그 다음 자른 문자를 printf를 이용해서 “./rawToROOT ”라는 문자를 붙여서 출력한다. printf 문법은 다들 아시시라 생각하고 생략한다.

이제 적당히 뒤에 “> run.sh”를 붙여서 결과를 파일로 출력한다음 실행시켜주면 끝!

 

Makefile

  • 기본구조
    • 목표: 의존파일들
      (탭문자)명령
  • 명령에 쓸 수 있는 특수 문자들
    • $@ – 목표 그대로를 의미함
    • $^ – 의존파일 전체 리스트를 의미함
    • $< – 의존파일에서 제일 첫번째 있는 파일을 의미함
    • $* – 목표에서 확장자를 뗀 파일명만을 의미함
    • ; \ – 명령 문장 끝에 써줘서 다음 줄이 같은 쉘에서 실행되도록 한다. 예를들어 첫번째 명령이 A라는 폴더로 들어가는거고 두번째 명령이 거기에 B라는 폴더를 만드는거라고 하면, 이 문자를 쓰고 안쓰고에 따라 A안에 B가 있느냐 A와 B가 같은 폴더안에 있느냐가 갈리게 된다. 두 문자가 셋트임에 주의.
    • @ – 명령 문장 제일 앞에 써서 명령어가 실행될때 쉘에서 보이지 않게 한다.
    • % – 모든것을 의미 (쉘에서의 * 같은 의미)
  • .PHONY
    • 이것도 나중에
  • .SUFFIXES – 지정된 확장자를 가진 파일에 대해 동일한 처리를 하도록 하는 명령어인데….
    아래 명령어로 대체 가능하다길래 무시하기로 하고 정리 안함

    • %.o: %.cc
      (탭문자)명령
  • 변수 정의법
    • VARIABLE = 어쩌구저쩌구 # 정의
    • $(VARIABLE) # 사용
  • 환경변수가 정의돼있는지 확인할 때 if문
    • ifdef ENVIRONMENT_VARIABLE
    • 어쩌구
    • else
    • 어쩌구
    • endif
  • 쉘에서 실행한 결과를 사용하고 싶을 때
    • $(shell 명령어)
  • 뒷쪽 이름에 앞쪽 이름을 다 붙이고 싶을 때
    • $(addprefix 앞, 뒤)
    • 출력되는 결과는 “앞뒤”. 만약 “뒤”에 오는 내용이 스페이스로 구분된 문자라면, 스페이스 다음에 나오는 문자에는 다 앞이 붙는다. 예를들어 “뒤 = a b c d” 라면 위 명령의 결과는 “앞a 앞b 앞c 앞d” 가 된다.
  •  쉘에서 ls를 쳐서 나오는 모든 cc확장자를 가진 파일을 리스트로 만들고 싶을 때
    • $(wildcard *.cc)
    • 만약 어떤 디렉토리 안에 들어가서 가져오고 싶으면 앞에 경로도 같이 써주면 된다.
  • 어떤 문자에서 단어를 치환하고 싶을 때
    • $(patsubst 이거를, 이걸로, 여기서)
    • 예) $(patsubst %.c, %.o, x.c.c bar.c)
      결과) x.c.o bar.o
  • 변수에 여러개의 아이템이 있는데, 한개만 지우고 싶을 때
    • $(filter-out 이거를,여기서)
    • 예)
      HEADER = A B C D
      HEADER2 = $(filter-out D,$(HEADER)) # 결과는 HEADER2 = A B C
  • 조건문도 사용할 수 있다. (ifeq, ifneq)
    • ifeq (A,B)
      내용
      else
      내용2
      endif

Byte 순서 (Big-endian & Little-endian)

Big-endian은 값을 앞에서부터 기록하고, Little-endian은 값을 뒤에서부터 기록한다고 알고있자. 예를들어, 0x12345678을 binary로 기록한다고 하면, 각각은 다음과 같이 기록된다.

  • Big-endian: 12 34 56 78
  • Little-endian: 78 56 34 12

C++에서 ‘#include <arpa/inet.h>’를 이용해 include 해 주면, Byte 순서를 바꿔주는 네가지 함수를 사용할 수 있다.

  • uint16_t ntohs(uint16_t)
  • uint32_t ntohl(uint32_t)
  • uint16_t htons(uint16_t)
  • uint32_t htonl(uint32_t)

각각 uint16_t 또는 uint32_t형 변수를 받아서, uint16_t 또는 uint32_t형 변수를 반환한다. 입력 된 변수의 주소값 Byte 순서를 바꿔서 반환하므로, 반환되는 값은 전혀 다른값이 돼 있다. 물론 값을 쓰려고 이런일을 하는건 아닐테니 그냥 참고사항으로 적어둔다.

위 함수들은 XtoY(s,l) 형태로 이해하면 되는데, X에서의 Byte순서의 (short, long) 변수를 Y에서의 Byte순서로 바꿔서 반환하라는 의미이다. 만약 X에서의 Byte순서와 Y에서의 Byte순서가 같다면 입력값이 그대로 반환된다.

참고로 uint16_t 와 uint32_t에서 u는 unsigned를 의하고, 16과 32는 각각 비트수를 의미, _t는 typedef를 이용해서 정의된 변수형이라는 의미이다. 따라서 uint16_t는 unsigned형 int이기 때문에 음수는 사용할 수 없고, 16비트이므로 2바이트의 크기를 가지는 변수형이라는걸 알 수 있다.