[만화가 있는 C] 4. 데이터 형

4. 변수는 쓰기 전에 선언해야 한다: 데이터 형(data type)


#include <stdio.h>
void main() {
    char c=129;
    printf("%d\n",c);
}

  위 프로그램의 실행결과는 얼마일까요? 다음과 같은 대답이 가능할 수 있습니다.

  (1) 129

  (2) char형은 -128~+127까지만 표현할 수 있는데, 129를 대입했으므로, 오버플로우overflow 에러이므로, 결과는 알 수 없습니다.

  C 언어를 잘 알고 있다고 생각하면서도 위와 같은 질문에 정확한 대답을 하는 사람은 많지 않습니다. 정답은 다음과 같습니다.

“char는 1바이트 정수형인데, 앞에 선언 변경자 unsigned 가 없으므로, 부호있는signed 1바이트 정수형입니다. C 언어는 정수를 나타내기 위해 2의 보수를 사용하는데, 129의 부호 있는 2의 보수 표현은 -127이므로, -127이 출력됩니다.”

  우리가 앞 장에서 2진수에 대해서 배웠습니다. 2진수의 자세한 표현을 이해하는 것은 중요합니다. 자료형data type의 내부 표현을 이래하는 것은 아무리 강조해도 지나치지 않습니다. 대부분의 컴퓨터는 정수의 음수를 표현하기 위해 2의 보수를 사용합니다. 일반적으로 정수의 음수를 표현하는 방법은 부호와 가중치(sign & magnitude)에 의한 방법, 1의 보수(1’s complement), 2의 보수(2’s complement) 방법 등이 있습니다. 각 표현의 특징을 살펴봅시다.

  부호와 가중치에 의한 방법은 가장 왼쪽 비트(MSB; most significant bit)를 부호 비트(sign bit)로 사용하며, 나머지 비트들을 가중치(magnitude)로 사용합니다. 3비트까지의 표현을 써 보면 아래 표와 같습니다.

 가장 왼쪽 비트는 가중치가 가장 크므로, MSB라고 합니다.


표현

000

001

010

011

100

101

110

111

0

1

2

3

-0

-1

-2

-3

 부호와 가중치에 의한 부호 있는 정수 표현(3비트의 예)

  만약 음수를 표현하지 않는다면, 0~7까지의 수를 표현하는 것이 가능합니다. 이것은 다음과 같은 공식으로 나타낼 수 있습니다.

0~2n-1

  위의 경우는 3비트를 사용하므로, 0~23-1의 범위의 정수를 표현할 수 있습니다. 110을 -2로 결정하는 것은 두 단계를 거칩니다.

  (1) 부호 결정: MSB가 1이므로, 음수입니다.

  (2) 값 결정: MSB를 제외한 나머지 비트들의 가중치를 계산합니다. 이진수 10이므로 그 값은 2입니다.

  이와 같이 부호와 가중치에 의한 방법에서는 MSB는 부호만 결정할 뿐 값에는 영향을 미치지 않습니다. 하지만 이 방법은 어떠한 컴퓨터도 정수의 음수를 나타내기 위해 사용하지 않습니다. 다음에 설명할 보수(complement number)를 사용하여 정수의 음수를 표현합니다.


  1의 보수와 2의 보수 각각에 대해 값을 결정한 표를 아래에 나타내었습니다.

표현

000

001

010

011

100

101

110

111

0

1

2

3

-3

-2

-1

-0

표현

000

001

010

011

100

101

110

111

0

1

2

3

-4

-3

-2

-1

 1의 보수, 2의 보수에 의한 부호 있는 정수 표현

  보수에 관한 사항은 앞 장의 “이진수”를 다시 참조하기 바랍니다. 이진수 100의 보수에 의한 값은 다음 두 단계를 거쳐 결정합니다.

  (1) 부호 결정: MSB가 1이므로 음수입니다.

  (2) 값 결정: MSB를 포함한 전체 비트의 보수가 값입니다. 100의 1의 보수는 011이므로 3입니다. 100의 2의 보수는 100이므로 4입니다.

  그러므로 이진수 100은 1의 보수에 의해 -3(10), 2의 보수에 의해 -4(10)입니다. 부호와 가중치에 의한 표현법과는 달리, 부호 결정 이후에 전체 비트가 값을 결정하기 위해 사용하였습니다. “이진수”에서 설명한 이점 때문에 컴퓨터는 2의 보수를 사용하여 정수 – 양수, 음수 모두 – 를 표현합니다. 그러면, 2의 보수 표현이 음수를 표현하는지, 양수만 표현하는지 어떻게 알 수 있을까요? 이러한 사항은 C 문법이 지원해 주어야 합니다. 우리는 1바이트의 부호 없는 정수형 변수를 선언하고 싶으면 다음과 같이 합니다.

 일반적으로 char는 아스키 1 문자(character)를 나타낼 수 있기 때문에, 문자형(character type)이라고도 합니다.

unsigned char i;

  부호 있는 정수형은 다음과 같이 선언합니다.

signed char i;

  2바이트, 4바이트 정수는 char 대신에 각각 short, int를 사용합니다. 그러므로 4바이트 부호 있는 정수는 아래와 같이 선언합니다.

signed int i;

일반적으로 부호의 유무를 나타내는 signed 나 unsigned는 생략하면 signed가 되므로, signed를 생략하여 아래와 같이 나타냅니다.

int i;

short나 long다음에는 이것이 정수(integer)임을 확실히 하기 위하여 int가 위치해도 됩니다. 그러므로

long int i;

라고 해도 같은 표현입니다. Win16플랫폼의 C언어에서는 int는 2바이트를 의미했고, long은 4바이트를 의미했습니다. 하지만, Win32와 Win64에서는 int와 long은 모두 4바이트의 정수를 의미합니다. 이제까지 설명한 변수의 형 선언 앞에 붙을 수 있는 변경자(modifier)를 포함한 정수 선언의 문법은 다음과 같습니다. 밑줄 친 부분은 생략하면 그 값이 디폴트(default)임을 의미합니다.

[signed|unsigned] [short|long] int <variable>;


초기화(initialization)

  변수가 선언되고 초기화되어야 한다면, 선언하면서 초기화하는 것이 간단하고 읽기 좋습니다. 아래의 예는 정수형 변수 i를 선언한 뒤 i를 1로 초기화하고 있습니다.

        int i;

        i=1;

  위의 코드는 다음과 같이 간단하게 적을 수 있습니다.

        int i=1;

  초기값은 브레이스({})로 묶어도 됩니다. 이러한 블록 구조의 초기화는 배열, 클래스, 구조체 등 복합형(compound type)의 변수 혹은 객체를 초기화하기 위해서 필요합니다. 일관성을 위해서 int같은 간단한trivial 형에 대해서도 브레이스를 사용하는 것이 가능합니다.


        int i={1};

  아래의 예를 참고하세요.

 

#include <stdio.h>

void main() {

    int i;

    int j=2;

    float k={1.2};

    i=1;

    printf("%d,%d,%f\n",i,j,k);

}

 

  결과는 아래와 같습니다.

        1,2,1.200000

 1.2가 1.200000로 인쇄된 것은 밑의 진보된 주제에서 설명합니다.

  정수integer같은 기본형의 초기화 외에 배열, 구조체, 클래스의 초기화는 각각의 주제가 나올 때마다 다룰 것입니다. 이러한 모든 초기화의 방법을 체계적으로 이해하는 것은 우리가 해야 할 일입니다.


함수형 초기화(functional initialization)

  C++의 클래스(class)가 소개된 이후 기본형의 함수형 초기화가 가능해졌습니다. 이것은 기본형의 생성자(constructor) – 존재하는 것은 아니지만 – 를 호출하는 것과 같은 문법형태이므로 자연스럽습니다. 예를 들면

int i=1;

int i(1);

처럼 적을 수 있습니다. 비록 후자의 i선언이 함수 i를 호출하는 것 같지만, 이것은 정수 변수 i를 1로 초기화하는 문장입니다. 함수 호출처럼 보이므로, 함수형 초기화라고 합니다.

  기본형의 함수형 초기화는 많이 사용하지 않는 형태입니다. 하지만, 반드시 함수형 초기화를 해야하는 곳이 있으므로, 함수형 초기화는 C++에서는 중요합니다. 함수형 초기화의 다른 주제들과 일관된 초기화uniform initialization는 ‘만화가 있는 C++’에서 다룰 예정입니다.


실수(real number)는 어떻게?

  우리는 2의 보수를 이용하여 정수의 음수를 표현함을 알고 있습니다. 하지만, 실수(real number)는 어떻게 표현할까요? 2의 보수 개념을 확장하면 쉽게 정수를 표현할 수 있습니다. 2바이트로 실수를 나타낸다고 생각해 봅시다. 상위 바이트(high byte)는 소수점 이상 부분을, 하위 바이트(low byte)는 소수점 이하 부분을 나타내도록 코드를 구성할 수 있습니다. 이러한 표기법은 소수점의 위치가 고정되어 있어서 고정 소수점(fixed point) 표기라고 합니다.

  2.3을 고정 소수점 표기법으로 나타내면, 2는 0000 0010, 3은 0000 0011 이므로 2바이트 실수를 저장할 때, 다음과 같이 저장할 수 있습니다.

0000 0010 0000 0011

그리고 이진열을 해석할 때 상위 바이트를 소수점 이상 부분으로, 하위 바이트를 소수점 이하부분으로 해석하는 것입니다. 이 표기법은 얼마나 큰 수, 또한 얼마나 정밀한 수를 나타낼 수 있을까요?

  소수점 이상 부분이 음수를 표현한다면, -128~127까지를 표현할 수 있습니다. 소수점 이하부분은 음수를 나타낼 필요가 없으므로, 0~255까지 표현할 수 있습니다. 그러므로 표현할 수 있는 가장 작은 수는 -128.0이며 가장 큰 수는 127.255입니다. 또한 표현할 수 있는 가장 정밀한 유효자리의 범위는, 0.999는 표현할 수 없으므로, 소수점 이하 유효자리 2자리까지입니다.

  이러한 고정 소수점 표현은 큰 수도 표현하지 못할 뿐더러, 정밀한 수도 표현하지 못합니다. 그러므로 큰 수도 표현할 수 있고, 정밀한 수도 표현할 수 있는 표현법이 필요합니다. 이것이 부동 소수점(floating point) 표기법입니다. 대부분의 컴퓨터는 실수를 표현하기 위해 부동 소수점 표기법을 이용합니다. C에서 실수의 형 이름이 real이 아니고, float인 이유는 실수를 표현하는 표기법의 이름에 기인합니다.

  실수의 2진 표기법을 이해하는 것은 가끔 필요합니다. 실수가 저장된 메모리 데이터를 읽었을 때, 실제 실수값을 알아내기 위해서는 실수가 2진수로 표현되는 방법을 알고 있어야 합니다.


부동 소수 표현(floating point notation): 진보된 주제

  [이 절은 구조체structure를 사용하고 있습니다. 일단은 건너뛰었다가 ‘구조체’까지 읽은 후에 다시 보기 바랍니다.]

  실수 역시 2진수로 표현되기는 하지만, 표현 방식은 2의 보수 방법과는 많이 다릅니다. 예를 들면, 4바이트 실수(float) -14.24는 컴퓨터에 어떻게 저장될까요?

  아래의 예는 실수 -14.24를 16진수로 인쇄하는 프로그램입니다. 프로그램이 구조체(structure), 공용체(union), 표준 스트림 라이브러리standard stream library를 사용하고 있으므로, 아직은 이해할 수 없습니다. 이 소스는 17장 ‘구조체’에서 자세히 설명합니다. 지금은 프로그램의 출력 결과에 주목합니다. -14.24는 16진수로 아래와 같이 표현됩니다.

0xc163d70a

2진수로는 아래와 같이 표현됩니다.

1100 0001 0110 0011 1101 0111 0000 1010

 

#include <iostream>

struct BITFIELD {//이것은 비트 필드 구조체입니다.
    unsigned m0:4;//아주 특별해 보이는 이 선언은 m0가 4비트를 차지하는
                  //것을 의미합니다.
    unsigned m1:4;
    unsigned m2:4;
    unsigned m3:4;
    unsigned m4:4;
    unsigned m5:4;
    unsigned m6:4;
    unsigned m7:4;
};//struct BITFIELD

union FLOAT {//공용체는 필드(field)를 공유합니다. f와 b는 같은 메모리를
             //공유하며, f의 크기가 32비트, b의 크기 역시 32비트이므로
             //실제 메모리는 64비트가 아닌 32비트가 할당됩니다.
    float f;
    BITFIELD b;
};//union FLOAT

void main() {
    FLOAT f;
    f.f=-14.24;
    //cout은 ostream 클래스의 전역 객체입니다.
    std::cout << f.f << std::endl << std::hex;
                        //endl과 hex 조작자(manupulator)는 출력
                        //스트림의 형식(format)을 조작합니다.
                        //이것은 ‘함수 포인터’에서 자세히 다룹니다.
    std::cout << f.b.m0 << f.b.m1 << f.b.m2 << f.b.m3
        << f.b.m4 << f.b.m5 << f.b.m6 << f.b.m7 << std::endl;
    //output: c163d70a■
}

 

 프로그램의 실제 출력 결과는 a07d361c인데 이것은 인텔 CPU가 역워드 방식으로 수(number)를 저장하기 때문입니다. 이 사항은 후에 ‘연산자’에서 자세히 다룹니다.

  결과는 아래와 같습니다.

        -14.24

        a07d361c

  이유를 살펴보기 위해, 먼저 실수를 수학적으로 나타내는 방법을 살펴봅시다. -14.24를 나타내는 방법은 다양합니다. 아래에 몇 가지 예를 나타내었습니다.

        …

        -0.01424×103

        -0.1424×102

        -1.424×101

        -14.24

        -142.4×10-1

        -1424×10-2

        -14240×10-3

        …

  컴퓨터는 이러한 방법 중에 소수점 이상의 자리를 모두 0으로 한 표현법인 -0.1424×102을 사용하는데, 소수점 이하 부분과 지수 부분만을 관리하는 이점과 큰 수와 정밀한 수를 같이 표현할 수 있는 이점 때문입니다. 이렇게 임의의 실수를 유효자리 수가 모두 소수점 아래에 오도록 변환하는 것을 정규화normalization라고 합니다.

  예를 들면, -14.24를 정규화하면, -0.1424×102이며, 3.141592를 정규화하면 0.3141592×101입니다.

  정규화를 하면 소수점의 위치가 부동floating하게 됩니다. 그래서 이러한 정규화의 결과를 저장하여 실수를 표현하는 방식을 부동 소수점 표현 방식floating point notation이라고 합니다.

  정규화의 결과를 컴퓨터에 세부분으로 나누어 저장할 수 있습니다. 부호sign, 지수exponential와 가수mantissa 부분이 그것입니다. -14.24의 경우 부호는 음수, 지수는 2, 가수는 1424를 저장합니다.

  컴퓨터는 2진수를 사용하므로, 실제의 정규화는 조금 다릅니다. 모든 C컴파일러는 4바이트 부동 소수점을 나타내기 위해 IEEE 754 표준 방식(IEEE 32-bit standard)을 사용하고 있으며, 이것은 제안된 키워드 float를 사용합니다. float보다 2배 정밀도(double precision)를 가지는 실수는 8바이트(IEEE 64-bit standard)이며, 키워드 double을 사용합니다. 이 장에서는 float표현만 다룹니다. float는 부호, 지수와 가수자리를 위해 각각 1, 8 그리고 23비트를 사용합니다.

 4바이트 실수인 float는 단일 정밀도(single precision)라고 합니다.

 부동 소수 표기: float(IEEE 32-bit standard)는 부호를 위해 1비트, 지수를 위해 8비트, 가수를 위해 23비트, 모두 32비트를 사용합니다.

  float의 정규화 식은 아래와 같습니다.

(-1)s(1.m)2e-127

  위의 식에서 s,m과 e를 결정하여, 각각의 32비트 자리를 채웁니다. s가 1이면 (-1)1은 -1이므로 음수를 의미하며, 0이면 (-1)0=1이므로 양수를 의미합니다.

  정규화를 하면, 소수점 이하 첫 번째 비트는 항상 1이므로 이 공간을 절약하기 위해, 처음 1은 항상 있는 것으로 간주하여, m의 자리에 포함시키지 않습니다.

  e는 음수를 나타내는 것을 피하기 위하여, 128초과 코드(excess-128 code)를 사용합니다. 예를 들면, e가 0이면, 지수는 -127을 의미하며, e가 128이면 1을 의미한다.

 이러한 코드 – excess-n code, BCD code, Gray code 등 – 가 어떻게 효과적으로 사용되고 있는지는 위키wiki를 참고하세요.

  이제 -14.24의 s,e와 m을 결정해 봅시다.


■ 단계 1: s의 결정

  부호는 음수이므로 s=1이다.

■ 단계 2: m의 결정

  먼저 14.24의 2진수를 구해야 한다. 14는 이진수로 아래와 같습니다.

1110

 14의 이진수: 14를 계속해서 2로 나눈 나머지를 거꾸로 씁니다.

0.24는 2진수로 아래와 같습니다.

0.0011 1101 0111 0000 1010

 0.24의 이진수: 계속해서 2를 곱해서 소수점 이상 첫째자리를 구합니다. 계속해서 2를 곱할 때는 소수점 이하만 고려합니다.

그러므로 14.24는 아래와 같습니다.

1110.0011 1101 0111 0000 1010

정규화 과정을 거치면 아래와 같이 표현됩니다.

1.1100 0111 1010 1110 0001 010×23

그러므로, 부동소수점 표현의 m은 소수점 이하 부분인 아래의 이진열이 됩니다.

1100 0111 1010 1110 0001 010

■ 단계 3: e의 결정

  정규화의 결과 지수 부분이 3이므로, e=130(e-127=3)이다. 130의 2진수는 아래와 같습니다.

1000 0010

  그러므로 위 프로그램의 출력 결과는 아래와 같습니다.

C163D70A

 -14.24의 float 표현: -14.24는 위의 그림처럼 저장됩니다. 이것을 16진수로 표현하면, C163D70A입니다.


부동 소수의 가감승제(addition, subtraction, multiplication and division)

  2의 보수 표현의 정수 가감승제는 컴퓨터 구조(computer architecture)등의 책에서 캐리 미리보기 가산기(carry look-ahead adder)등을 다룬 내용에서 알고리즘을 찾아 볼 수 있습니다. 그렇다면, 부동 소수 표현의 가감승제는 어떻게 구현 할 수 있을까요?

 이 알고리즘을 직접 구현해 보는 것은 많은 도움이 됩니다. 예를 들면, 128비트 2진수 덧셈을 하려면, 이러한 알고리즘을 직접 구현해야 합니다. 이것을 구현한 예는 Alan Parker, “Algorithms and Data Structures in C++”, CRC Press, 1993 에서 찾아 볼 수 있습니다.

  여기에 관한 대답은 매우 고전적인 것입니다. sin(), cos()등의 함수와 더불어 많은 부동 소수 계산 알고리즘이 연구되었습니다. 그러므로, 자세한 알고리즘은 모르더라도 이러한 것은 추상화(abstraction)시켜서 생각합니다. 하지만, 이러한 실수 계산은 정수에 비해 많이 느립니다. 이러한 계산을 위한 실수 전용 협동 중앙 처리 장치(math co-processor)의 가격은 높았으며, 일반 사용자에게는 특별한 것으로 간주되던 적이 있었습니다. 그래서 범용 CPU와는 별도로 판매되었으며, 협동 프로세서(co-processor), 수치 연산 프로세서(numerical processor)로 불렸습니다.

볼런드 C++ 3.1의 대화상자: 부동 소수(floating point)를 위해 Emulation을 사용할지 80387을 사용할지 설정할 수 있습니다.

  하지만, 펜티엄(Pentium)급 CPU 이상부터는 이러한 협동 프로세서가 범용 CPU에 포함되었습니다. 486급 이하에서 동작하는 C 컴파일러에서는 부동 소수 계산을 위해 라이브러리를 사용할 지, 협동 프로세서를 사용할지를 설정하는 대화상자(dialog box)를 볼 수 있었습니다. 하지만, 펜티엄급 이상에서 동작하는 최근 컴파일러에서는 이러한 대화상자를 찾아 볼 수 없게 되었습니다.

 볼런드 C++ 빌더 3의 Project Options 대화상자: 부동 소수에 대해 Pentium 60의 한때 버그인 FDIV를 수정하는 체크 박스외에 라이브러리를 선택하는 부분은 없습니다.

Visual Studio 2013의 프로젝트 속성 페이지: 코드 생성 페이지의 ‘부동 소수점 모델’에서 실수 처리와 관련된 모델을 선택할 수 있습니다.


형의 종류(sort of types)

  우리는 지금까지 기본형 중에서 정수와 실수를 나타내는 int, float를 살펴보았습니다. C++의 형은 몇 개의 바이트로 이루어져 간단한 해석만을 필요로 하는 기본형과 그렇지 않은 복합형으로 크게 구분할 수 있습니다.

  C++에서 지원하는 형의 종류에는 다음과 같은 것들이 있습니다. 그 형이 나타내는 자세한 내부 구조와 범위는 여기서 명시하지 않습니다. 그러한 형들은 그 형들을 설명할 필요가 있을 때마다 적절히 설명할 것입니다. 여기서 우리는 형의 종류와 이름을 알아두는 정도로만 파악 하겠습니다.

  ■ 기본형(fundamental type)

        char    : 1바이트의 정수를 나타낼 수 있습니다.

        short   : 2바이트의 정수를 나타낼 수 있습니다.

        long   : 4바이트의 정수를 나타낼 수 있습니다.

        float   : 4바이트로 실수를 표현합니다.

        double : 8바이트로 실수를 표현합니다.

        bool   : C++에 새로 추가된 형으로 false,true를 표현합니다.

        wchar_t : Wide CHARacter Type을 의미하는데, 2바이트 문자형을 나타냅니다.

  ■ 복합형(compound type)

        array           : 배열array은 같은 형의 변수를 하나의 대표이름으로 여러 개 선언하기 위해 사용합니다.

        pointer         : 주소 변수를 선언하기 위해서 사용합니다.

        reference       : 참조reference는 C++에 새로 추가되었습니다. 파라미터 전달에 사용된 참조는 파라미터의 값을 전달하지 않고 참조를 전달합니다.

        class           : 클래스class는 다른 모든 데이터 형을 포함할 수 있는 자료 구조입니다. C++에 추가되었습니다.

        struct          : C에서 구조체는 여러 다른 타입을 포함하는 타입입니다. C++에서 구조체는 클래스와 거의 같습니다.

        union          : 구조체와 거의 같지만, 필드field가 같은 메모리 공간을 공유합니다.

        pointer to non-static class member : C++에 추가된 포인터 타입 입니다. 기본 주소에 대한 상대 주소relative address로 데이터를 참조하기 위해서 사용합니다. 새로운 연산자 .* 와 ->* 를 사용해서 접근할 수 있습니다.


특별한 형 void

  우리는 2장 ‘수학 함수를 C함수로’에서 함수의 리턴 형과 파라미터 자리에 사용된 void를 살펴보았습니다. void가 사용되는 경우는 다음과 같은 4가지 경우입니다.

■ 함수 선언에서 파라미터 리스트가 비었음을 나타냅니다.

        int func(void);//func()는 파라미터를 가지지 않습니다.

■ 함수가 값을 리턴하지 않는 것을 나타냅니다.

        void func(int n);//func()는 값을 리턴하지 않습니다.

■ 일반 포인터(generic pointer)를 나타냅니다. C에서 void*는 어떠한 것도 가리킬 수 있습니다.

        void* ptr;//ptr에는 어떤 포인터도 대입할 수 있습니다.

■ 형 변환type conversion에서 리턴형을 무시합니다.

        extern int errfunc();//int타입의 에러 값을 리턴합니다.

        …

        (void)errfunc();//리턴 값을 버립니다.

  마지막 2가지 경우는 각각 6장과 8장의 ‘포인터, []연산자’와 ‘연산자’를 읽어야만 이해할 수 있습니다.


실습문제

1. 아래 프로그램 코드를 Visual C++ 6.0과 Borland C++ 4.5에서 실행시킨 결과가 있습니다. 결과가 다르게 출력된 이유를 설명하세요.

#include <stdio.h>

int i,j;

void main() {
        printf("%p,%p\n",&i,&j);
}

        결과(VC++): 004135CC,004135D0

        결과(16bit BC++): 6B6F:0ACE,6B6F:0AD0

#include <stdio.h>

void main() {
    int i,j;

    printf("%p,%p\n",&i,&j);
}

        결과(VC++): 0064FDF8,0064FDF4

        결과(16bit BC++): 6F6F:2016,6F6F:2014

 

#include <stdio.h>

void main() {
    int i;
    int j;

    printf("%p,%p\n",&i,&j);
}

        결과(VC++):  0064FDF8,0064FDF4

        결과(16bit BC++): 1117:2016,1117:2014

 

2. 소수점 이상의 어떤 수를 2로 계속해서 나눈 나머지를 거꾸로 쓰는 것이 왜 2진수가 됩니까? 책에서 보여준, 소수점 이하의 부분을 2진수로 구하는 과정은 또 왜 그렇습니까?

@

만화가 있는 C

Leave a Reply