[작성자:] snowall

  • 삶에 중독된다

    모든 인간이 중독된 것, 삶.

    반드시 가져야만 하고, 구하기도 쉽고, 끊을 수 없으며, 만약 끊는다면 그것으로 이미 죽음을 맞이해야만 하는 것. 바로 삶이다.

    새해를 맞이하면서, 삶에 중독되어 습관적으로 나이를 먹고 있는건 아닌지 생각해 보았다.

  • 군 복무 기간 단축

    난 아직 군대에 갔다오지 않았다. 따라서, 최근 노무현 대통령의 발언을 액면 그대로 믿는다면 난 노빠가 될지도 모른다.

    한 6개월 줄여서 18개월로 만든다고 한다. 여기에 대해, 주성영이라는 아저씨가 차라리 군 가산점 제도를 부활시키라고 주장한다. 아마 이건 여성가족부에서 반대할 것이다. 생각해보자. 군 가산점 제도를 없앤 것은 남녀차별을 없애기 위해서다. 물론 이런 얘기를 하려면 여성도 2년간 번 소득중에 병장 월급에 준하는 10만원 정도만 남기고 나라에 갖다 바치라는 얘기가 나올지도 모르지만 말이다.

    아무튼, 명백한건 군대를 가지 않은 남자들에게는 군 가산점보다 군 복무기간 단축이 훨씬 매력적인 떡밥이라는 것이다. 물론 나 역시 군 가산점보다 복무기간 단축을 훨씬 선호한다. 왜? 난 군 가산점을 쓸 일이 없을 테니까. 공무원은 내 장래희망에 해당하지 않는다.

  • C언어 기본 문법

    C언어는 언어다. 따라서 문법이 있다.

    모든 명령문은 ;으로 끝나야 한다. ;이 없으면 끝나지 않은 것이고, ;이 있으면 무조건 일단 끝난 거다. 엔터나 공백은 모두 한칸으로 처리되고, 아무튼 ;만이 끝을 나타낸다. -_-;

    //뭐라고?

    한줄짜리 주석. 이거 뒤에 있는 글자들은 그 줄이 끝날 때 까지 전부 무시된다.

    /* 어쩌라고 */

    여러줄 짜리 주석. 물론 한줄짜리 주석 달 때도 쓸 수 있다. 별표로 둘러싸인 부분의 안에 있는 건 아무리 길더라도 전부 무시된다.

    함수는 다음과 같이 사용한다

    함수(인자);

    이렇게 적어두면, 함수 안에 인자가 들어가서 적당히 처리된다. 인자는 여러개가 될 수도 있는데, 그때는 쉼표를 이용해서 구별한다. 함수 만드는 법은 따로 설명하도록 하겠다.

    연산자들 : =, +, -,*, /, %, ++, —

    대입연산자”=”는 오른쪽에 있는 걸 왼쪽에 있는 것에다가 집어넣는다.

    +,-,*,/는 각각의 양쪽에 있는 것들을 계산해서 그 계산값을 되돌린다. /는 왼쪽에 있는 값을 오른쪽에 있는 값으로 나눈다. %는 왼쪽에 있는 값을 오른쪽에 있는 값으로 나눈 나머지를 찾아준다.

    ++와 –는 정수에서 1을 더하거나 빼는 연산자이다. 가령 a++;는 a에 1을 더한다. 이건 ++a;라고 쓸 수도 있는데, 둘 사이의 차이는 a++는 일단 a에 있는 값을 다른데다가 쓰고나서 1을 더한다는 뜻이고, ++a는 일단 1을 더한 후에 계산하는데다가 쓴다는 뜻이다. 다른 명령어를 같이 쓰지 않는 경우에는 a++와 ++a는 아무런 차이가 없다.



    [각주:

    1

    ]



    –연산자는 1을 빼는 작용을 한다.

    #include

    #include”yyy.yyy”

    #include는 지정한 화일을 포함시킨다. 이때, 포함시킨다는 뜻은 말 그대로 “있는 그대로” 집어넣는다는 뜻이다. 프로그램에 xxxxxxx라는 문자열을 적어넣는 것과, xxxxxxx라는 문자열이 포함된 xxx.xxx라는 파일을 include하는 것은 완전히 똑같다. 따라서, include구문은 보통 공통적으로 여러 화일에서 쓰이는 것들을 모아놓고 여기저기서 불러와서 쓸 때 사용한다. 가령, 어떤 함수를 정의했는데 그게 여기저기서 쓸 일이 많다면 헤더화일로 적당히 만들어 놓고서 불러오면 되는 것이다. 그럼 함수가 작동을 안할 때 헤더화일만 고치면 되므로 아주 좋다. 꺽쇠와 따옴표에 차이가 있는데, 꺽쇠는 지정된 화일을 컴파일러가 설치된 기본 라이브러리 위치에서 찾고, 따옴표는 컴파일하는 화일이 있는 위치에서 지정된 화일을 찾는다.

    참고로, #이 들어간 명령을 선행처리기(preprocessor)라고 하는데, define, typedef등이 있다.

    #define ABCD xxxx

    이런식으로 쓰면, 프로그램에서 ABCD라는 구문이 나올 때마다 항상 그것은 자동으로 xxxx로 치환된다. 가령, 원주율을 3.1이라고 알고 있다가, 좀 더 정확한 계산을 해서 3.14라는 걸 알았다면, 모든 곳에서 3.1을 3.14로 고칠 필요 없이, 애초에 #define PI 3.1로 해 놓고 PI로 모든 원주율을 계산한 후에, 나중에 첫줄만 3.1 대신에 3.14로 고치면 된다는 것이다.

    참고로 #이 들어간 선행처리기 명령들은 ;를 쓰지 않는 예외사항이다.

    ;를 쓰지 마라.

    괄호의 사용

    {}는 구문을 묶을 때 쓴다. 가령, “넌 A도 하고 B도 하고 C도 해야 돼”라고 명령하고 싶은데, 기본적으로 C는 한줄 처리하고나서는 그 다음에 있는 명령만 한다. 그럼 {A; B; C;}라고 쓰면 그게 모두 한 줄로 처리되는 거다. 이건 실제로 써보면 안다.

    ()는 식을 묶거나 함수에 인자를 넘겨줄 때 쓴다. (a+b)+c는 당연히 a와 b를 먼저 더하고, 그 다음에 c를 더하라는 뜻이 된다. 그리고 function(parameter)형식으로 사용한다는 건 앞서 이야기 했다.

    main()

    C언어는 함수 위주의 프로그램이다. 따라서, 최초에 실행해야 하는 적어도 한개의 함수는 있어야 하는데, 그게 바로 main함수이다. C언어로 만든 프로그램을 실행시키면 기본적으로 main을 가장 먼저 실행시킨다.

    1. 이런 의미에서 C언어의 확장팩이라고 하는 C++을 왜 이렇게 이름붙였는지 알 수 있다. 아마 C언어를 배우고나서 하나 더 배우라는 뜻 아닐까?

      [본문으로]

  • 구조체

    구조체는 뭐냐…

    변수 여러개를 묶어둔 것을 의미한다. 원래, C에서 쓸 수 있는 변수 형태는 정수, 실수, 긴 실수 정도인데, 우린 벡터도 써야 하고 복소수도 써야 한다. 이런 경우, 새로운 형태를 지정해 줘야 한다. 사용법은 간단하고 복잡하다.


    struct 구조체

    {

    int x;

    int y;

    }

    이렇게 해 두면 구조체가 선언된다. 그리고 구조체에 있는 값을 다른데서 가져다가 써야 한다면 항상 그 앞에 struct를 붙여줘야 한다. 안그러면 구조체가 구조체라는걸 모르기 때문이다.

    실제로 구조체 형태의 변수를 쓸 때는 위와 같이 구조체를 선언해주고, 다음과 같이 사용해야 한다.

    struct 구조체 변수이름;

    만약 이 변수 안에 있는 x라는 녀석의 값이 필요하면 다음과 같이 불러오면 된다.

    변수이름.x

    물론 y가 필요하면 점 찍고 y를 쓰면 된다.

    아래의 소스는 내가 C언어에서 복소수를 처리하기 위해서 직접 만든 코드이다. 사칙연산, 켤레복소수, 실수부분, 허수부분, 절대값 등을 처리할 수 있게 되어 있다. 한번 분석해 보면 구조체가 어떻게 작동하는지 알 수 있을 것이다.

    struct cnumber
    {
    double x;
    double y;
    };

    //addition
    struct cnumber add_cnum(struct cnumber z, struct cnumber w)
    {
    struct cnumber a={z.x+w.x,z.y+w.y};
    return a;
    }

    //subtraction
    struct cnumber sub_cnum(struct cnumber z, struct cnumber w)
    {
    struct cnumber a;
    a.x=z.x-w.x;
    a.y=z.y-w.y;
    return a;
    }

    //multiplication
    struct cnumber mul_cnum(struct cnumber z, struct cnumber w)
    {
    struct cnumber a;
    a.x=z.x*w.x-z.y*w.y;
    a.y=z.x*w.y+z.y*w.x;
    return a;
    }

    //complex conjugate
    struct cnumber conj_cnum(struct cnumber z)
    {
    struct cnumber a;
    a.x=z.x;
    a.y=-z.y;
    return a;
    }

    //norm
    double norm_cnum(struct cnumber z)
    {
    double a;
    z=mul_cnum(z,conj_cnum(z));
    a=z.x;
    return a;
    }

    //division : z is divided by w
    struct cnumber div_cnum(struct cnumber z, struct cnumber w)
    {
    struct cnumber a;
    a=mul_cnum(z,conj_cnum(w));
    a.x=a.x/norm_cnum(w);
    a.y=a.y/norm_cnum(w);
    return a;
    }

    //real part
    double re_cnum(struct cnumber z)
    {
    double a;
    a=z.x;
    return a;
    }

    //imaginary part
    double im_cnum(struct cnumber z)
    {
    double a;
    a=z.y;
    return a;
    }

    //complex phase
    struct cnumber phase_cnum(struct cnumber z, double k)
    {
    struct cnumber x={cos(k),sin(k)};
    struct cnumber m=mul_cnum(z,x);
    return m;
    }

  • 알고리즘

    알고리즘은 어떻게 만들까?

    난 알고리즘을 만드는 방법을 체계적으로 배운 적은 없다. 다만, 그때그때 필요한 일을 시키기 위해서 컴퓨터의 생각 방식과 나의 생각 방식 사이의 연결 관계를 찾았을 뿐이다. 아마 이 작업을 알고리즘을 만드는 작업이라고 하는 것이라고 생각한다. 프로그램 제작을 직업으로 삼아서 일하시는 분들과 비교하면 아주 허접한 수준이지만, 혹시라도 누군가에게 도움이 될 수도 있다면 그것도 좋지 않을까 해서 몇자 적어둔다. 만약 틀린 부분이 있다면 지적해도 좋다.

    앞서 얘기한바와 같이, 컴퓨터가 생각하는 것과 내가 생각하는 것 사이의 연결고리를 찾아내는 것이 알고리즘을 만드는 작업이다. 그렇다면, 일단 두가지를 알아야 한다. 1.컴퓨터가 생각하는 방식과 2.내가 생각하는 방식이다.

    1.컴퓨터가 생각하는 방식

    컴퓨터의 사고 구조는 단순하다. 숫자들을 아주 많이 늘어놓고서, 그 숫자들을 적당히 골라서 산수 계산을 하고, 그 결과를 저장한다. 그리고 이러한 일을 무작정 반복할 수 있다. 이러한 사실로부터 알 수 있는 몇가지 사실들은 컴퓨터에게 주는 자료는 숫자가 되어야 한다는 것과, 그 숫자로부터 얻을 수 있는 결과들은 역시 숫자가 된다는 것이다. 컴퓨터에게 A+B를 입력해봐야 A와 B가 뭔지 알려주지 않으면 그 출력은 A+B일 뿐이다.

    2.내가 생각하는 방식

    보편적인 사람이 생각하는 방식은 아주 복잡하다. 사람은 컴퓨터와 달리 논리적인 생각을 한다. 그리고 계산의 지름길을 찾아낼 수 있다. 컴퓨터가 하는 계산이 무조건 미친듯이 반복해서 답을 찾아내는 것이라면, 사람이 답을 찾는 계산은 대충 생각해보고 이미 알려진 사실로부터 답을 유도하는 것이다. 컴퓨터가 생각하는 방식으로는 아직 인간의 증명을 따라가기는 힘들다.

    하지만, 사람이 할 수 없는 일들을 컴퓨터에게 시킬 수는 있다. 가령, 10425의 계승을 정확히 계산해 내는 일이라든가 등등. 10425의 계승을 사람보고 계산하라고 시키려면 누구라도 일단 짜증부터 내고 하든가 말든가 할 것이다. 하지만 컴퓨터에게 일을 시키는 것은 쉽다. 프로그램을 만들고 컴파일 한 후에 돌리면 된다.

    3.알고리즘

    따라서, 내가 얻고 싶은 정보와 입력할 수 있는 정보를 숫자로 나타내는 것이 가장 중요하다. 이러한 이유로, 컴퓨터를 이용해서 푸는 방법을 이용한 것이 바로 수치해석이다. 수치해석은 손으로 풀 수 없거나 풀기 힘들거나 아직 안 풀린 문제들을 당장 활용하기 위해서 근사적인 답을 찾아내는 방법을 제안해 준다. 물론 근사적인 답이라도 얼마든지 실용적으로 활용할 수 있으므로 이 분야는 연구할 가치가 있는 분야가 된다.

    가령, 미분방정식을 풀어야 한다면, 찾아야 할 함수를 아주 많은 미지수로 두면 된다. 이러한 미지수들 사이의 관계식이 바로 미분방정식이 되고, 입력하는 숫자들은 바로 초기값이나 경계값이 된다.

    4.실제 알고리즘은?

    가령, 1부터 100까지 더하는 프로그램을 만든다고 하자

    그럼 그 가상 코드는 다음과 같다.

    출력(1+2+3+…+100)

    자, 이 코드는 허무할 정도로 쉽다. 하지만 100까지 더하는 게 아니라 10000까지 더해야 한다면? 프로그램의 길이가 너무 길어지지 않을까? 입력하다가 차라리 계산하고 싶어질 것이다. 잔머리를 굴려라. 컴퓨터는 산수에 있어서는 아주 끝내주는 녀석이다.

    숫자=1

    반복(만약 숫자가 100과 같거나 작으면 계속하고, 100보다 크면 그만해라)[합=합+숫자, 숫자=숫자+1]

    출력(합)

    이러면 좀 짧아졌나? 게다가 원하는대로 100보다 더 많은 숫자를 넣을 때도 고칠 곳이 딱 두군데 뿐이다. 물론 코드의 길이를 더 줄일 수 있는 여지가 있지만, 그건 각자 해 보시라.

    컴퓨터 프로그램 언어에는 기본적으로 다음과 같은 명령들이 있다

    A=B

    이 명령은 B를 A에 대입한다. 정확히는, =의 오른쪽에 있는 녀석이 가진 값들을 왼쪽에 있는 녀석의 값으로 입력해 준다.

    만약(조건)[실행문] ; 아니면[실행문] ;

    보통은 if ~ else 문으로 주어지는데, 계산을 하다가 멈추거나, 다른 조건들을 대입할 필요가 있을때 등, 아무튼 뭔가 판단할 때 사용할 수 있다.

    반복(조건)[실행문]

    이건 조건이 맞으면 조건이 틀릴 때 까지 계속 실행문을 반복실행한다. 따라서, 실행문 안에 원하는 만큼 계산을 했으면 조건을 틀리게 만드는 명령을 넣지 않으면 무한루프에 빠져버리게 될 것이므로 조심하자.

    +, -, *, /, %

    당연히 사칙연산 계산이다 %는 앞에 있는 수를 뒤에 있는 수로 나눈 다음에 그 나머지가 궁금할 때 사용한다.

    실제로, 이것만 이용해서도 꽤 많은 것들을 할 수 있다. 가령, 3n+1문제라든가, 조화진동자 문제 등을 해결할 수 있다는 거다.

  • Hello, world!

    Hello, world!

    가장 기본적인 영어 문장이다.

    누군가에게 인사를 할 때 사용할 수 있으며, 그때는 world 대신에 상대방의 이름을 적으면 된다.

  • Hello, world!

    \documentclass{article}

    \begin{document}

    Hello, world!

    \end{document}

    TeX의 가장 기본적인 구조이다.

  • Hello, world!

    #include

    main(0)

    {

    printf(“Hello, world!”,\n);

    }

    C언어의 가장 기본적인 프로그램.

  • 핵공격에 못 견디는 인터넷

    기사는 아래 링크 참고.

    http://www.inews24.com/php/news_view.php?g_serial=240620&g_menu=020600

    이번 지진이 강타한 곳이 해저 케이블 밀집 지역이라고 했다. 전문가가 얘기하기로, 이번 사건으로부터 배울 점이 이 지역에 더 많은 케이블을 설치할 필요가 있다고 한다. 이건 번역을 잘못했거나 이 아저씨가 잘못 얘기했거나 둘 중 하나임이 명백하다. 왜? 지진은 원래 났던데서 계속 일어난다. 그러므로 지진이 난 곳에 케이블이 끊어져서 문제가 됐다면, 그 케이블과 같은 역할을 하는 케이블을 지진이 나지 않은 곳을 경유하도록 연결해야 하는 것이다. 지진때문에 끊어지는 케이블이라면 몇개가 있든지 상관 없이 끊어진다. 인터넷이 핵 공격에도 견딜 수 있다는 얘기는, 우회할 수 있는 경로가 아주 많이 있기 때문에 어느 한 곳의 링크가 깨지더라도 다른 곳을 경유해서 원하는 곳의 정보를 얻을 수 있다는 뜻이다. 이번 사건은 허브와 허브를 연결하는 링크가 깨졌기 때문에 발생한 장애이다. 따라서 이 사고를 막으려면 허브와 허브를 연결하는 링크를 더 많이 만들어야 한다. 하지만 같은 지역에 더 많은 케이블을 설치하는 건 종이위에 연필로 덧칠하는 것과 같다.

  • 과거로 명령을 보내서 사람을 자기 맘대로 조종할 수 있다

    방금 엄청난 장면을 봤다. S선배님이 N모 선배님을 자기 맘대로 조종하는 모습을 말이다. 한가지 흥미로운건, S선배님이 한 명령을 그대로 N선배님이 수행하는 건 맞는데, 시간적 순서를 보면 N선배님의 행동이 S선배님의 명령보다 이르다는 점이다.

    그렇다. 이 현상을

    “S선배님은 드디어 시간을 뛰어넘어 과거의 타인에게 명령을 보내는 능력을 얻었다”



    해석

    할 수도 있다.

    이 아이디어는 S모 선배님의 아이디어를 그냥 퍼왔다. -_-;