posted by bluelimn 2016.01.15 10:45

int가 사용 word size를 사용하기 때문에 32bit에서는 4byte, 64bit에서는 8byte를 사용한다.

이것은 상당히 유명한 내용이기 때문에 많이들 안다.

그런데 놓치기 쉬운 것은 long 이다.

linux에서 기본적으로 long이 unsigned int 로 되어 있기 때문에 마찬가지로 int와 동일한 크기를 가진다.


좀 더 깊이 들어가면 data model에 따라 조금씩 다르다고 하는데 자세히는 모르겠다


64-bit data models

Data model

short (integer)

int

long (integer)

long long

pointers/
size_t

Sample operating systems

LLP64/
IL32P64

16

32

32

64

64

Microsoft Windows(x86-64 and IA-64)

LP64/
I32LP64

16

32

64

64

64

Most Unixand Unix-likesystems, e.g. Solaris,LinuxBSD, and OS X;z/OS

ILP64

16

64

64

64

64

HAL Computer Systems port of Solaris toSPARC64

SILP64

64

64

64

64

64

"Classic"UNICOS[35](as opposed to UNICOS/mp, etc.)

 

<wikipedia : https://en.wikipedia.org/wiki/64-bit_computing>


간단한 test로 sizeof를 확인해봤다


printf("long: %d\n", sizeof(long));

printf("int : %d\n", sizeof(int));


32bit 
long: 4
int : 4

64bit

long: 8

int : 4


예상과 다르게 int가 4로 나왔다. 역시나 wiki는 똑똑한 사람들이 편집하는구나.

posted by bluelimn 2008.05.29 01:15
#include <stdio.h>
int main()
{
    int number1, number2;
    printf("정수 2개를 입력: ");
    scanf("%d %d", &number1, &number2);
    printf("number1 = %d, number2 = %d", number1, number2);
    return 0;
}

무지 간단한 코드다. 하지만 제대로 된 값이 입력되지 않으면 치명적인 결과가 나올수도 있다. 가령 제대로 된 값이 입력될 때까지 반복문을 돌리는 코드에서 숫자대신 문자를 입력하면 무한루프에 갇히는 경우가 종종 발생한다. 어떻게 처리하는 것이 좋을까?

사람들이 쉽게 지나치는 경우가 많지만 많은 함수가 return값을 제공하고 있다. 가능한 많은 함수의 return값을 생각하라. printf와 scanf의 경우도 마찬가지다. 특히 scanf의 return값을 꽤 유용하고 똑똑하다. scanf는 변수에 제대로 들어간 갯수만큼 return해준다. 만약 위의 코드에서 하나는 숫자 하나는 문자를 입력하면 return값은 1이 된다.
이를 이용해서 간단하게 오류처리를 해보자.

#include <stdio.h>
int main()
{
    int number1, number2;
    do{
        printf("정수 2개를 입력: ");
        fflush(stdin);                          //입력버퍼(stdin)를 비우라는 명령
    }while(scanf("%d %d", &number1, &number2) != 2);
    printf("number1 = %d, number2 = %d", number1, number2);
    return 0;
}

이 코드는 제대로 된 입력값이 들어올 때까지 계속 반복하게 된다.
posted by bluelimn 2008.05.29 00:35

유클리드 호제법 : 기원전 300년경 기하학자 유클리드가 주장하여 그의 이름을 딴 공식으로 알려져 있다.
두 자연수 A,B에 대하여 A를 B로 나누었을 때 몫을 Q, 나머지를 R이라고 하면(A = BQ+R)
A,B의 최대공약수는 B,R의 최대공약수와 같다.
<증명> A,B 둘의 최대공약수 G
A = aG, B = bG (a,b는 서로소)
(A = BQ+R, B = bG 이므로)
bGQ+R = aG
=> R = (a - bQ)G
--------------------------
A = aG
B = bG
R = (a-bQ)G
그러므로 A,B의 최대공약수와 B,R의 최대공약수는 G로 서로 같다.

========================================================================
#include <stdio.h>
unsigned int gcd(unsigned int valuer1, unsigned int value2);
unsigned int lcm(unsigned int value1, unsigned int value2);

int main()
{
    unsigned int value1, value2;
    printf("자연수 2개를 입력하시오 : ");
    scanf("%d %d", &value1, &value2);
    printf("최대공약수 : %d\n", gcd(value1, value2));
    printf("최소공배수 : %d\n", lcm(value1, value2));
    return 0;
}

반복문사용 gcd..


재귀호출사용 gcd..


int lcm(int value1, int value2)
{
        int temp;
        temp = gcd(number1, number2);
        return (number1/temp)*number2;
}

======================================================================
위의 소스는 우선 돌아가는 것 같지만 약점이 있다.
입력값을 전혀 체크하지 않는다는 것! 만약 자연수를 입력하지 않는다면 문제가 발생할 가능성이 크다.
0 0을 입력한다면? 만약 수를 입력하지 않고 문자를 입력해 버린다면?
간단히 오류체크를 추가해서 main을 바꿔보자.

int main()
{
    unsigned int value1, value2;
    do{
        printf("자연수 2개를 입력하시오 : ");
        scanf("%d %d", &value1, &value2);
    }while(value1 <= 0 || value2 <= 0);
    printf("최대공약수 : %d\n", gcd(value1, value2));
    printf("최소공배수 : %d\n", lcm(value1, value2));
    return 0;
}

간단히 do-while을 사용해서 자연수가 아닌 정수(0,음수)는 걸러주도록 했다.
숫자 이외의 값이 입력되는 경우는 찾아보기 쉽게 다른 글로 다시 써야겠다.

posted by bluelimn 2008.05.01 11:56

#include <stdio.h>

unsigned long factorialUsingRecursion(unsigned long n);
unsigned long factorialUsingLoof(unsigned long n);

int main(void)
{
        printf("10! = %lu\n", actorialUsingRecursion(10));
        printf("10! = %lu\n", factorialUsingLoof(10));
        return 0;
}

// 재귀호출을 이용한 factorial계산
// 종료조건(if)을 가장 먼저 적어주는 것에 유의
// 재귀호출은 어떻게 돌아가는지가 중요한 것이 아니라
// 어떤 수식을 그대로 옮겼느냐만 생각하면 된다.
unsigned long factorialUsingRecursion(unsigned long n)
{
        if(n <= 1) return 1;
        return(n*factorial(n-1));
}

unsigned long factorialUsingLoof(unsigned long n)
{
        unsigned long result, i;

        result = 1;
        for(i=2; i<=n; i++)
        {
                result = result * i;
        }
        return result;
}

posted by bluelimn 2008.04.27 00:51

삽입정렬(Insert Sort)

more..


힙정렬(Heap Sort)
초보 프로그래머의 실력을 보고자 할 때 우선순위 큐를 물어보는 경우가 많다. 실제 기술 면접 때도 우선순위 큐를 다루는 문제가 자주 나오니 확실하게 기억해두자.
우선순위 큐는 힙(Heap)을 사용해야 한다. 물론 삽입정렬과 큐를 사용해도 무관하지만 그것은 O(N^2)알고리즘이다. 이에 반해 Heap은 O(N log N)이다. 엄청난 차이를 보이는 알고리즘.. 그러한 차이를 알고있느냐가 관건인 것이다. 돌아만 가는 코드를 내놓은 프로그래머는 실무에선 그다지 필요하지 않다.

more..



쉘 정렬(Shell Sort)

more..


출처 : http://www.tipssoft.com
퍼갈때 출처를 달아달라는 말이 있었다..ㅎ
posted by bluelimn 2008.04.27 00:41

선택정렬(Selection Sort)

more..


버블정렬(bubble sort)

more..



퀵정렬(Quick Sort)

more..


자료출처 : http://www.tipssoft.com
posted by bluelimn 2008.03.19 22:42
완전제곱이란?

more..


인터넷 카페를 돌다가 누군가 완전제곱 판별 소스를 올려놓은 것을 봤다. 소스를 보면서 문제를 풀 때 바로 컴퓨터 앞에서 작성을 시작하는 것이 얼마나 위험한 일인지 다시 생각하게 되었다.
아래는 까페 관리자가 올린 소스다. 프로그래밍에 꽤 신경을 많이 쓰는 것이 보이는 사람인데 문제를 풀 때는 가끔 실수를 하기도 하니까.. 만약 이 글을 본다면 기분나쁘게 생각하지 말았으면 좋겠다.

more..

좀 더 많은 수를 입력받을 수있게 하기 위해 unsigned long을 사용하고 있는 것을 알 수 있다.(int는 컴파일러에 따라 다른 결과를 가져올 수도 있다.)
무리하게 if문 내에 핵심내용을 기술하는 것 외에도 치명적인 실수가 있다. 프로그램이 실행되는 동안 불필요한 작업을 반복해서 하고 있는 부분이 있다. 도대체 어디가? 아래 글을 보기 전에 한번 차근자근 따져보기 바란다.


================================================================================
불필요한 작업은..

more..


그래서 소스를 조금 수정해봤다.

more..


이래놓고 봐도 도저히 마음에 들지 않는다. 이럴 땐 문제를 처음부터 다시 인식하는 과정이 필요하다.
완전제곱의 정의 : 다른 정수의 제곱으로 표현되는 정수
1조건 : 정수여야 한다.
2조건 : 다른 정수의 제곱으로 표현된다.(다시 말하면 기하평균이 정수다.)

이렇게 생각해보면 기하평균이 정수인지 확인해보면 되는 것이다. 기하평균이란 어떠한 수의 제곱근을 말하는 것으로 루트를 씌운 값이라고 생각하면 쉽다. 기하평균이 정수인지는 어떻게 판단하지? 난 아래와 같은 코드를 생각했다.

more..


꽤 길고 복잡한 소스가 두줄로 줄었다. 심지어 이정도라면 함수를 따로 구현할 필요조차 없이 그냥 한줄로 넣어주면 된다. 문제를 제대로 인식하고 어떤 방법으로 접근할 것인가를 깊이 생각해보는 것은 프로그래머의 중요한 습관이다. 열심히 생각하고 노력하는 사람들도 실수를 많이 하는데 처음부터 함부러 뛰어드는 습관이 들어버린다면 당신은 프로그래머가 아니라 코더로 만족해야 한다.
posted by bluelimn 2008.03.10 23:48
커리큘럼을 복사해온 것을 보다가 연산자부분은 그냥 넘어가면 안되겠다 싶어서 손을 대게 되었다.
특히 비트연산자는 눈여겨볼 필요가 있다.
연산자 - 단항, 산술, 쉬프트-비트, 관계, 논리, 삼항, 대입
대략 이런 식으로 분류할 수 있단다.

1. 단항 연산자
말 그대로 operend가 하나다. 같은 수식도 위치에 따라 쓰임이 달라지는데 특히 단항 연산자가 그렇다.
종류 : + , - , ++, --
예 : int a = 10;이라고 가정해보자.
+10, -10, +a, -a (상수나 변수가 음수인지 양수인지를 나타낸다.)
++a, a++, --a, a-- (많이 사용되지만 결코 쉽지 않은 연산이다. ++은 a의 값을 1증가시켜 a에 대입하고 --는 그 반대다. 하지만 ++a처럼 연산이 앞에(선행) 있으면 해당 line에서 이미 연산이 되고 a++처럼 뒤에(후행) 있으면 다음 줄로 넘어갈 때 연산이 된다. 이 연산은 상수에는 사용할 수 없다.)

more..

프로그래밍 습관에 대해서는 다른 카테고리에 계속 글을 올리겠지만 증가,감소연산자를 대입연산과 함께 사용하는 것은 아주 위험한 일이다.
=========================================
1.           a = 10;
             a = ++a - --a + a++;
             printf("%d\n",a);
-----------------------------------------
 2.        a = 10;
            printf("%d\n", ++a - --a + a++);
=========================================
1번과 2번 소스는 출력 결과가 다르게 나온다. 그런데 중요한 것은 이런 수식이 사용되면 안된다는 것이다. 이런 수식을 잘 사용한다고 자랑하는 것은 멀쩡한 손 놔두고 발로 젓가락질 할 줄 안다고 자랑하는 것과 비슷하다. 누누히 말하지만 소스를 보는 사람이 바보라고 생각하고 최대한 알아보기 쉽게 작성해야 한다.

2. 산술 연산자
종류 : + - * / %
예 : 우리가 생각하는 사칙연산과 똑같이 사용하면 된다. 사칙연산이라면서 왜 다섯개야?라고 생각한 당신! 눈치가 빠르다.
+ : 더하기
- : 빼기
* : 곱하기
/ : 나누기
%: 모듈러
+ -
는 단항연산에서도 사용되었다. 어떻게 쓰이느냐에 따라 연산이 달라진다는 것이다. 양쪽에 operend(피연산자)가 있으면 산술연산으로 계산되니 염두해두자. 그리고 C언어에서 이러한 연산들을 구분하는 것으로 띄어쓰기도 작용을 하므로 주의해야 한다. space bar한번에 전혀 엉뚱한 연산이 작동할 수도 있다.
b - --a, b - - -a, b-- -a 이 세가지가 모두 다르다는 말이다.
/연산은 나누기와 같은데 주의할 점은 C언어에서 int의 나누기연산이다. int는 정수를 취급하기 때문에 나누기 연산의 몫에서 정수부분만 가져온다. 이때 내림을 하는데 15/4의 경우 3.75가 아니라 3이 나온다.
%연산은 유용한 사용이 많으니 잘 기억해두자. 사칙연산도 아니면서 같이 껴 있으면 얼마나 중요한 녀석인지 감 잡아야 한다. 이녀석은 15%4의 결과로 3이 출력된다. %의 사용은 다방면으로 많은데 그중 흔히 사용되는 경우가 반복문 내에서 if문과 함께 사용되는 경우다.
if( i % 3 == 0) 이렇게 사용하면 i가 3의 배수일 때마다 if문이 작동한다.

3. 관계연산자
종류: <, >, <=, >=, ==, !=

A < B : A가 B보다 작다
A > B : A가 B보다 크다
A <= B : A가 B보다 작거나 같다. (작아도 true, 같아도 true)
A >= B : A가 B보다 크거나 같다. (커도 true, 같아도 true)
A == B : A와 B는 같다.
A != B : A와 B는 같지 않다.
주의할 것은 앞에 있는 A가 중심이고 식의 결과는 true나 false가 된다. C의 경우 true나 false의 개념이 없기 때문에 true는 1이 false는 0이 return된다.
(TIP: C에서는 0이면 false이고 나머지 다른 값이면 true가 된다.)

4. 삼항연산자
종류: 수식?A:B
예: (a>b) ? a++ : b++;
수식의 값이 참(true)이면 A가 실행되고 거짓(false)이면 B가 실행된다. 잘 사용되지 않는 수식이지만 복잡하고 긴 수식을 한방에 조지는 마법같은 효과가 있다.

5. 논리연산자
종류: &&, ||, !
ADN, OR, NOT이라고 부른다.
논리연산자는 계산식을 operend로 하는 것을 원칙으로 한다.
A && B : 두 식이 모두 참이다. (두 식이 모두 true면 true, 아니면 모두 false)
A || B : 둘중 하나는 참이다.(두 식이 모두 false면 false, 아니면 모두 true)
!A : A의 결과를 반대로~ (A가 true면 false, A가 false면 true)

6. 비트연산자
사실 내가 비트연산자 때문에 글을 쓰게 되었다. 비트연산은 조금쯤 깊이있게 생각해야 하기 때문에 일반적인 프로그래밍에서 많이 사용하지 않는 것이 좋다. 하지만 비트연산은 산술연산보다 확실히 빠르므로 반복횟수가 많고 계속적인 연산이 있을 경우, 비트연산이 편리한 수식일 경우 비트연산을 잘 사용하면 효율적이다.
종류 : &, |, ~
&(AND) : 비트가 둘다  1이면 1 아니면 0
|(OR) : 비트가 둘다 0이면 0 아니면 1
~(NOT): 비트 반대로
예)

more..

이해만 확실히 하면 전혀 어려운 개념이 아니다. 다만 2진수로 생각해야 한다는 것이 문제다.

7. shift(쉬프트)
종류 : >>, <<
에) 20 << 3 이거 결과로 80 나온다. 왜 그런지 알아보자
20 : 0000 0001 0100
<<3
결과 : 0000 1010 0000
왼쪽으로 3칸 이동한 것을 볼 수 있다. shift연산자는 방향에 따라 이동하기때문에 헷갈리기 쉽다.
화살표가 있다고 생각하면 기억하기 쉽다.
<<------- 요녀석 왼쪽으로 이동하라는 이야기
------------>> 요녀석 오른쪽으로 이동하라는 이야기
주의: >> 요녀석 주의해야 한다. <<는 오른쪽에 0으로 무조건 채우면 된다.
그런데 >>는 MSB에 따라 달라진다. 그러니까 가장 왼쪽에 있는값이 1이면 1로 채우고 0이면 0으로 채워야 한다. 그러니까 양수면 0으로 채우고 음수면 1로 채우라는 이야기!
posted by bluelimn 2008.03.03 00:14
난수 생성 함수를 사용하여 1부터 6 사이의 값을 생성시켜서 주사위 던지기를 시뮬레이션 할 수 있다. 주사위를 6000번 던졌을 때에 나오는 눈의 빈도를 조사하고 확률을 구하여라. (주사위 n이 나올 확률은 (눈금 n이 나온 빈도수)/6000)

more..


posted by bluelimn 2008.02.28 00:15

컴퓨터가 정수를 표현하는 방식은 한가지만 있는 것이 아니다. 흔히 학교에서 배우는 방식은 처음 MSB로 음수, 양수를 표현하고 나머지 비트로 2의 보수법을 취하여 수를 계산하는 방식이다.
그런데 다른 방식도 많이 있다. 그중 하나가 bias를 이용하는 방식이다.(이름이 생각나지 않지만 이러한 방식은 부동소수의 지수를 나타낼 때 많이 사용된다.)

중심되는 숫자를 기준으로 그보다 작은 수는 음수, 큰 수는 양수로 계산하는 방식이다.
예를 들어 0~15까지 4자리 이진수로 나타내는 수가 있다고 하자.
여기에서 0은 0000이 아니라 중간 값인 1000이 된다.


10진수 MSB방식 bias방식
-8(최소) 1000 0000
-3 1101 0101
-2 1110 0110
-1 1111 0111
0 0000 1000
1 0001 1001
2 0010 1010
3 0011 1011
7(최대) 0111 1111

문제>0~65535까지의 양수값을 입력받아 -32768 ~ 32767까지의 수를
MSB방식의 16자리 2진수로 표현하라.
입력 : inputfile.txt
출력 : consol
입력파일에는 정수만 입력되며 0보다 작거나 65535보다 큰 값이 입력되면 오류메시지를 출력한다.

입력:
123
4561
7892
1
65535
65536
32768
32767
32769
-1

출력:
-32645 : 1000 0000 0111 1011
-28207 : 1001 0001 1101 0001
-24876 : 1001 1110 1101 0100
-32767 : 1000 0000 0000 0001
 32767 : 0111 1111 1111 1111
ERROR! Input value of 65536 is out range for this program.
32768 : 1000 0000 0000 0000
     0 : 0000 0000 0000 0000
    -1 : 1111 1111 1111 1111
     1 : 0000 0000 0000 0001
ERROR! Input value of -1 is out range for this program.
-32769 : 0111 1111 1111 1111


==============================
참고자료로 올린 cpp파일은 비트연산을 이용한 출력을 하고 있다.
스스로 문제를 풀어보고 내가 작성한 소스와 비교해보라.
시스템에 따라 컴퓨터가 MSB방식을 채택하고 있지 않은 경우도 있다.
이러한 경우에 대비하여 printToBinary함수를 어떠한 환경에서도 같은 결과를 출력할 수 있도록 수정해보자.
소스나 문제에서 잘 이해가 가지 않는 부분이 있다면 질문 남기도록.

티스토리 툴바