본문으로 바로가기

[C] 자료형 - 2 (실수형, 상수)

category 개발자과정준비/C 2020. 9. 25. 17:15
반응형

실수형

 정수형의 범위를 넘는 큰 수와 부동 소수를 다루기 위해 실수형 float, double형이 존재한다. 일반적인 시스템에서 float형은 4바이트 크기를 가지며, double형은 8바이트 크기를 갖는다. 실수형의 데이터는 메모리 내에서 부호 부분과 가수부 및 지수부의 세 부분으로 나누어 저장된다.

 float형 숫자의 크기는 32비트이다. 이 중에서 1비트는 부호를 나타내고, 8비트는 지수부와 부호를 나타내고, 나머지 23비트는 가수부이다. 따라서 가수부는 10진수로 7자리까지 나타낼 수 있다. 실수형 상수의 자료형은 double형으로 간주된다.  실수형 상수 뒤에 f를 붙이면 float형, L을 붙이면 long double형으로 정해진다.

 

 

13.5 (10) 을 2진수로 바꾸는법?

 

 

6.125 (10)을 2진수로 변환해보자.

계속 2를 곱해줌으로써 정수부분을 소숫점 뒤에 입력하고, 0.0이 나올때까지 반복한다.

 

 

 소숫점이 딱 떨어져서 비교적 간단하게 나왔지만 숫자에따라 무한반복이 나올수도있기 때문에 10진수를 완전히 2진수로 바꿀 수는 없다. => 오차가 발생한다.

 그래서 프로그램할때는 소숫점을 있는 숫자는 쓰지 않는게 좋다.(변환이 잘 안되서 반올림같은게 일어난다) 

 

 정수를 저장할때는 16진수로 메모리에 0A (16) 로 저장되지만, 소숫점은 어떻게 저장되는지 알기위해 만들어진 표준이 IEEE 754 이다. IEEE 754 IEEE에서 개발한 컴퓨터에서 부동소수점을 표현하는 가장 널리 쓰이는 표준이다. 

 

 IEEE 754에는 32비트 단정밀도(single-precision), 64비트 배정밀도(double-precision)에 대한 형식을 정의하고 있다. 

C에서는 float는 단정밀도, double은 배정밀도와 대응된다.

 

 IEEE 754의 부동소수점 표현은 크게 세 부분으로 구성되는데, 최상위 비트는 부호를 표시하는 데 사용되며, 지수 부분(exponent)과 가수 부분(fraction/mantissa)이 있다.

 

부호비트가 0일때는 양수, 1일때는 음수로 정의한다

 

단정밀도 float형(a)                   배정밀도 double형 (b)

 

 

6.125 (10) 가 IEEE 754 에 의해 어떻게 저장되는지 살펴보자.

 

우선 정규화를 진행해야한다.(정규화는 정해진 규칙대로 모양을 만드는 것을 뜻한다.)

 정규화를 하는 방법은 앞에 1만 남기고 나머지는 소숫점 뒤로 보내주면된다. 즉, 1.나머지숫자 로 만들어 준다.

6.125를 2진수로 변환하면 110.001 (2) 이었으므로 1.10001 x 2^2 을 해주면 원래 값에 변화가 없으면서 정규화로 변환해준 값이라고 볼 수 있다.

 

이때 소숫점 뒤인 10001 을 가수부라고한다. 2^2를 제곱승인 2를 지수부라고 한다.

 

이제 6.125를 C로 작성해서 어떻게 메모리에 할당되는지 살펴보자.

 

스택은 밑에서부터 채워지기때문에 변수를 만들수록 위로 채워진다. 비쥬얼 스튜디오는 쓰레기값을 cc 로 채워넣었다.

해당 코드를 작성하고 디버깅모드로 실행하고, 메모리창을 실행해보자.

#include<stdio.h>

int main() 
{
	float fNum = 6.125f;
	printf("%f\n", fNum);
	return 0;
}

메모리에 6.125 가 16진수로 저장된 것을 확인할 수 있다

 

 

이때 00 00 c4 40  을 33 33 c3 40 (6.1 (10) 의 16진수)  으로 바꿔보자.

마우스로 클릭하면 수정할 수 있다

 

 

바꾼 다음에 F10을 눌러서 printf 를 실행해보면 6.1이 출력되있는 것을 볼 수 있다.

 

 

 

상수

상수는 크게 이름이 있는 상수(심볼릭(Symbolic) 상수)와 이름이 없는 상수(리터럴(literal)상수)로 나눌 수 있으며, 자료형에 따라서도 나눌 수 있다. 상수란 변경 분가능한 데이터를 의미한다.

100, 200, 300은 리터럴이다.

 

 

정수 상수

 정수형 상수는 범위가 제한되어 있는 점을 제외하고는 수학에서와 같지만, 숫자 표기때 자리수를 나타내는 콤마(,)를 사용하지 않는다.

 

 정수 상수는 10진수, 8진수, 16진수 형태로 표현할 수 있다.

1) 정수 상수가 0x나 0X로 시작하는 경우에는 16진수로 해석된다. 이때 a부터 f 혹은 A부터 F각각 10부터 15를 의미한다.

2) 0으로 시작하면 8진수로 해석한다.

3) 그렇지 않은 경우, 10진수로 해석한다.

 만약 정수 상수 앞에 '-' 부호가 오면, 이는 정수 상수에 단항 연산자를 적용한 것으로 인식하며, 부호는 상수의 일부로 취급하지 않는다. 정수 타입의 표현에 대한 정보를 표준 헤더 limits.h에서 제공한다.

#include <stdio.h>

int main(void) {
	printf("정수형 상수 100을 10진수, 8진수, 16진수로 출력하는 프로그램\n");
	printf("10진수 : %#d, 8진수 : %#o, 16진수 : %#x\n\n", 100, 100, 100);

	printf("정수형 상수 100을 10진수, 8진수, 16진수로 출력하는 프로그램 #없을때\n");
	printf("10진수 : %d, 8진수 :  %o, 16진수 : %x\n\n", 100, 100, 100);

	printf("정수형 상수 크기를 출력하는 프로그램\n");
	printf("The size of int 67 is %3d\n", sizeof(67));
	printf("The size of int 67L is %3d\n\n", sizeof(67.0));

	// 자료형의 크기가 어떤지 출력하는 예제
	printf("자료형의 크기 나열\n");
	printf("char : %d,  short : %d,    int : %d \n", sizeof(char), sizeof(short), sizeof(int));
	printf("long : %d,  long int : %d, long long : %d \n", sizeof(long), sizeof(long int), sizeof(long long));
	printf("float : %d, double : %d,   long double : %d \n", sizeof(float), sizeof(double), sizeof(long double));
}

sizeof는 크기를 알려준다.  sizeof(67) 에서 67은 정수형이므로 4byte이다. 따라서 sizeof(67) 67의 크기를 나타내는 것이므로 4가 된다.

 

 

문자 상수

 문자 상수는 문자 한 개 이상을 작은따옴표( ' ) 로 둘러싸서 표현한다. 또한, 소스에서 직접 입력이 불가능하거나 불편한 코드값이나 광역 문자를 지원하기 위한 특별한 방법이 제공되는데, 이를 확장열(escape sequenece)라 한다. 확장열은 특정 제어문자나 특수문자를 표현할 수 있게 해준다. 확장열은 하나의 문자 상수로, 반드시 백슬래쉬(' \ ')와 함께 작은따옴표로 묶어서 하나의 문자로 표시해야 한다.

 

이스케이프 시퀀스

 아스키코드의 번호는 전부 외우기가 힘드므로 이스케이프 시퀀스를 사용하도록 권장한다.

 

 문자열 상수는 0개 이상의 문자를 큰따옴표( " )로 둘러싸서 표현한다.

 

 

 

 

실습예제

1. 255보다 작은 10진수를 입력받아 화면에 문자로 출력하는 프로그램을 작성하시오.

// 255보다 작은 10진수를 입력받아 화면에 문자로 출력하는 프로그램을 작성하시오.
#include <stdio.h>
int main() {
	int iNum;
	printf("255보다 작은 정수를 입력하시오 : ");
	scanf("%d", &iNum);
	printf("숫자의 ASCII 코드 : %c\n", iNum);
}

 

 

 

2. 삼각형의 넓이를 구하는 프로그램

//삼각형의 넓이를 구하는 프로그램
#include <stdio.h>
int main() {
	int Width, Hight;
	printf("밑변과 높이를 입력하세요 : ");
	scanf("%d %d", &Width, &Hight);
    
	int Sum = (Width * Hight) / 2;
	
    printf("삼각형의 높이 : %d\n", Sum);
}

 

 

 

3. 3개의 정수(각각 0이상 6미만)를 입력받아 그들의 총합과 평균을 출력(평균은 소수점 둘째 자리에서 반올림하여 출력)

// 3개의 정수(각각 0이상 6미만)를 입력받아 그들의 총합과 평균을 출력
// 평균을 소수점 둘째 자리에서 반올림하여 출력
#include <stdio.h>
int main() {
	int iNum1, iNum2, iNum3;
	printf("3개의 정수를 입력하세요(각각 0이상 6미만) : ");
	scanf("%d %d %d", &iNum1, &iNum2, &iNum3);

	printf("총합 : %d \n", (iNum1+iNum2+iNum3) );
	printf("평균 : %.2f \n", (float)(iNum1 + iNum2 + iNum3) / 3);
}

 

 

 

 

4. 키보드로 알파벳 하나를 입력받아, 이를 소문자나 대문자로를 변환하여 출력하는 프로그램 작성

#include <stdio.h>
int main() {
	char ch;
	printf("알파벳을 하나 입력하세요 : ");
	scanf("%c", &ch);

	if (ch >= 'A' && ch <= 'Z') // 대문자 A~Z 인가?
	{
		printf("\n대문자를 입력하셨습니다.\n");
		printf("소문자로 변환 : %c\n", ch + 32);
	}
	else if (ch >= 'a' && ch <= 'z') // 소문자 a~z인가?
	{
		printf("\n소문자를 입력하셨습니다.\n");
		printf("대문자로 변환 : %c\n", ch - 32);
	}
	else
		printf("\n알파벳을 입력하지 않으셨습니다\n");
}

 

대문자 알파벳의 아스키코드 범위(A~Z) : 65 ~ 90

소문자 알파벳의 아스키 코드 범위(a~z) : 97 ~ 122

 

소문자 아스키 코드값 - 32 = 대문자 아스키 코드값

대문자 아스키 코드값 + 32 = 소문자 아스키 코드값

 

 

 

 

5. 화씨온도를 입력받아 섭씨온도로 출력하는 프로그램을 작성

//화씨온도를 입력받아 섭씨온도로 출력하는 프로그램을 작성
#include <stdio.h>
int main() {
	int iNum1;
	printf("화씨 온도(℉)를 입력하세요 : ");
	scanf("%d", &iNum1);

	int iNum2 = 1.8 * (float)(iNum1 - 32);
	printf("섭씨 온도는 : %.2f℃ 입니다.\n", (float)iNum2);
}

 

 

6. 월급의 실 입금액을 계산하는 프로그램

//월급의 실 입금액을 계산하는 프로그램
#include <stdio.h>
int main(void) 
{
	int bonbong, bouns, total;          // 본봉, 보너스, 총수입액
	double tax, real_income, tax_rate;  // 세금, 실수입액, 세율
	bonbong = 230;
	bouns = 60;
	printf("세율을 입력하세요(퍼센트) >>  ");
	scanf("%lf", &tax_rate);  // 키보드로 세율 입력
	total = bonbong + bouns; // 총 수입액은 본봉 + 보너스
	tax = total * (tax_rate/100);
	real_income = total - tax;
	printf("\n실 수입액은 %.3lf 입니다\n", real_income);

	return 0;
}

반응형