Notice
Recent Posts
Recent Comments
Link
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Development Log

[CS50] C언어 - 하드웨어의 한계 본문

성장 여행기/CS50

[CS50] C언어 - 하드웨어의 한계

gu-su 2022. 3. 25. 04:48
컴퓨터는 작성한 프로그램을 구동하기 위해 다양한 물리적 장치를 사용한다.
그 중 하나는 메모리로, 프로그램이 필요한 정보가 저장되는 곳이다. 
메모리의 용량은 무한하지 않기 때문에, 때로는 프로그램에 우리가 의도하지 않은 오류가 발생한다.

 

RAM (Random Access Memory)

  • 사용자가 자유롭게 내용을 읽고 쓰고 지울 수 있는 기억장치이다.
  • 컴퓨터가 켜지는 순간부터 CPU는 연산을 하고 동작에 필요한 모든 내용전원이 유지되는 내내 RAM에 저장된다.
  • 유한한 크기의 비트만 저장할 수 있기 때문에 때때로 부정확한 결과를 내기도 한다.
즉, 컴퓨터가 할 수 있는 일에는 근본적인 한계가 있다.
저장 공간의 크기가 정해져 있으므로 저장 가능한 숫자 역시 정해져 있다.
실제로 연산에도 한계가 있다.

 

부동 소수점 부정확성

코드 

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    // 사용자에게 x 값 받기
    float x = get_float("x: ");

    // 사용자에게 y 값 받기
    float y = get_float("y: ");

    // 나눗셈 후 출력
    printf("x / y = %.50f\n", x / y);
}

결과

x: 1
y: 10
x / y = 0.10000000149011611938476562500000000000000000000000

 

문제점 : float에서 저장가능한 비트 수(32bit, 4byte)가 유한하기 때문에 정확한 결과인 0.1이 아닌 다소 부정확한 결과가 나온다.

=> double은 float의 2배인 64bit(8byte)를 사용한다. 즉, float보다 double로 계산할 경우 더 정확하게 계산할 수 있다.

 

하지만 컴퓨터는 완벽하지 않기때문에 컴퓨터는 계산할 수 있는 값들 중에 1/10에 가장 가까운 값을 저장하는 것이다.
무한한 숫자들을 100% 정확하게 저장할 수 없기 때문이다.

 

정수 오버플로우

코드 : 정수를 계속 키우는 프로그램

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    for (int i = 1; ; i *= 2) // 조건이 비어있는 것은 true 와 같다. 즉, 무한 루프이다.
    {
        printf("%i\n", i);
        sleep(1);
    }
}

결과

...
1073741824
overflow.c:6:25: runtime error: signed integer overflow: 1073741824 * 2 cannot be represented in type 'int'
-2147483648
0
0
...

문제점 : i를 2배씩 증가해서 값이 계속해서 커지다 보니 앞자리에 1을 더할 비트조차가 없어졌다. 
=> 10억을 넘기자 앞으로 넘어갈 1의 자리가 없어진 것이다.

=> int는 32bit 이므로 그 이상의 숫자는 저장할 수 없는 것이다.

 

 

오버플로우

  • 변수가 담을 수 있는 최대 허용 범위를 벗어난 값을 저장해 예상치 못한 결과가 나오는 현상이다.

 

오버플로우로 인한 실제 사건

1. Y2K 문제

컴퓨터가 처음 발명된 1900년대 중반에 사람들은 저장공간을 절약하기 위해(너무 비싸서) 연도를 마지막 두자리수로 저장했다. (ex. 1999 → 99, 1973 → 73) 마치 50년뒤에는 컴퓨터를 사용하지 않을 것처럼..

1999년에 새해가 오면 99에서 00으로 정수 오버플로우가 발생하고, 새해가 2000년이 아닌 1900년으로 인식되는 문제가 있었다. 세계는 수백만 달러를 투자해서 프로그래머들에게 더 많은 메모리를 사용해서 이 문제를 해결하도록 했다. 

 

2. 비행기 보잉 787

비행기를 구동 후 248일이 지나면 모든 전력을 잃는 문제가 있었다. 왜냐하면 강제로 안전 모드로 진입했기 때문이다.

이는 소프트웨어의 변수가 248일이 지난 뒤에 오버플로우가되어 발생하였기 때문이다.

248일을 1/100초로 계산하면 대략 2의 32제곱이 나옵니다.

보잉을 설계할때 사용한 변수보다 너무 커졌던 것이다. 이를 해결하기 위해 주기적으로 재가동을 하여 변수를 다시 0으로 초기화했습니다.

 

다루고자 하는 데이터 값의 범위를 유의하여 프로그램을 작성하는 것이 중요하다.

 

think about

1) Y2K와 보잉787과 같은 문제를 방지하기 위해서는 프로그램을 어떻게 설계해야 할까요?

더보기

- 오버플로우가 발생하기 전에 변수를 초기화 시킨다.

- 더 큰 메모리를 사용한다.

- 오버플로우가 발생하는 것을 고려해 예외처리를 한다.

 

David J. Malan의 강의

 

모두를 위한 컴퓨터 과학 (CS50 2019)

부스트코스 무료 강의

www.boostcourse.org