CS 기초/C언어

[CS50] 하드웨어의 한계

담크 2021. 8. 3. 17:31

컴퓨터는 프로그램을 구동하기 위해서 다양한 물리적 장치를 이용합니다. 그중 하나가 아래 보이는

메모리 혹은 램이라는 것으로 프로그램이 필요한 정보가 저장되는 곳입니다. 이러한 램의 용량은 유한하기 때문에 때로는 프로그램에서 의도하지 않은 오류가 발생하기도 합니다.

 

지금까지는 의도적이던 아니던 사용자의 실수로 인해 에러가 발생했는데 램(RAM : Random Access Memory)은 유한한 크기의 비트만 저장할 수 있기 때문에 때로는 컴퓨터에서 부정확한 결과를 나타내기도 합니다.

 

그렇다면 어떠한 예시가 있는지 알아봅시다.

 

부동 소수점 부정확성

x / y의 결과를 출력하는 코드를 작성해보겠습니다.

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

int main(void){
    float x = get_float("x : ");
    float y = get_float("y : ");

    printf("x / y = %f \n", x / y);
}

실행해보면

우리가 알고 있는 결과와 같이 잘 나오는 것을 알 수 있습니다.

하지만 여기서 결과를 소수점 50번째 자리까지 출력해보면 어떻게 될까요?

응..?  뭔가 이상한 값이 되어버렸습니다.

이유는 float의 저장 가능한 비트수가 유한한데(32비트) 소수점 50번째자리수는 저장가능한 비트수를 초과했기 때문에 컴퓨터가 계산할 수 있는 값 중 1/10에 가장 가까운 값을 저장합니다. 그렇기 때문에 정확하지 않은 다소 부정확한 결과를 내는 것입니다.

 

정수 오버플로우

비슷한 오류로 1부터 계속 x2를 해서 출력하는 코드를 작성해보겠습니다.

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

int main(void){
    for(int i = 1; ;i *= 2){
        printf("%i\n", i);
        sleep(1);
    }
}

sleep(1)은 출력 결과를 1초 간격으로 늦춰주는 코드입니다. <unistd.h>를 include 해줘야 사용 가능합니다.

출력 결과를 보면

'

이렇게 처음엔 잘 나오다가

일정 숫자를 넘어가니까 에러가 발생하면서 0만 출력이 됩니다. 10억이 넘어가면서 앞으로 넘어갈 1의 자리가 없어졌기 때문인데 이는 int형이 저장 가능한 비트수를 초과한 것입니다.

다른 표현으로 111(2)은 10진법으로 7을 나타냅니다 여기서 1을 더하면 8이 되는데 8은 이진법으로 1000(2)입니다. 만약 이진법으로 표현 가능 한수가 3자리라면 1은 사라지고 메모리상에는 000만 남게 되겠죠

 

이러한 오버플로우 문제는 실생활에서도 종종 발견되는데

실제로 보잉 787이라는 비행기는 구동 후 248일이 지나면 강제로 안전모드에 들어가 모든 전력을 잃는 문제가 발생했다고 합니다. 이는 소프트웨어의 변수가 248일이 지난 후에 오버플로우가 되어 일어나는 문제였다고 하는데요 보잉사에서는 이를 해결하기 위해 보잉 787을 주기적으로 재가동하여 변수를 0으로 만들어주는 작업을 했다고 합니다.

 

또한 1999년에 큰 이슈였던 Y2K문제는 한 번씩 들어보셨을 겁니다. 예전에 연도를 저장할 때 1995년이면 95만 저장했던 관습이 있었는데 99년에서 2000년이 될 때 2000년이 아닌 1900년으로 인식되는 문제가 있었습니다. 이후 수백만 달러를 투자해서 더 많은 메모리를 활용해 이러한 문제를 해결했다고 합니다.

 

'CS 기초 > C언어' 카테고리의 다른 글

[CS50] 사용자 정의 함수, 중첩 루프  (0) 2021.08.02
[CS50] 자료형, 형식 지정자, 연산자  (2) 2021.08.01
[CS50] 조건문과 루프  (0) 2021.07.30
[CS50] 문자열  (0) 2021.07.29
[CS50] C 기초  (0) 2021.07.28