C언어 float 나누기 - ceon-eo float nanugi

C 예제.

정수 끼리의 나눗셈의 결과를 소수로 나오게 해보자!!

정수 / 정수 연산을 통해 결과가 소수점이 존재할 때 출력을 해보면

내가 생각하기엔 당연히 소수점 이하의 값도 출력이 될거라 생각했지만..

5 / 2 의 결과 값은 2가 나옵니다..

컴퓨터는 정수/정수 의 연산을 할 경우 결과가 소수점이 있다해도 정수/정수 이므로

소수점 아래 값은 그냥 제거해 버리기 때문에 이런 현상이 나오게 됩니다 ㅠ_ㅠ

내가 원하는 소수값을 출력하게 하기 위한 형변환 및 꼼수를

예제 소스를 통해 알려드리도록 하겠습니다.

예제 소스.

#include <stdio.h> int main() { int n1 = 0, n2 = 0; double ave = 0; printf("두개의 정수를 입력 하세요 : "); scanf("%d %d", &n1, &n2); // 정수/정수 ave = (n1+n2)/2; printf("입력받은 두수의 평균 : %.2lf\n\n", ave); // 형변환을 통한 소수/정수 ave = 0; ave = (double)(n1+n2)/2; printf("입력받은 두수의 평균 : %.2lf\n\n", ave); // 꼼수를 이용한 정수/소수 ave = 0; ave = (n1+n2)/2.0; printf("입력받은 두수의 평균 : %.2lf\n\n", ave); return 0; }

결과.

위의 결과를 보시면 (n1+n2) / 2 연산을 하고 출력한 첫번째 결과는 더블형의 변수 ave를 이용해

소수점 두번째 자리까지 출력을 했지만 2.00 이라는 결과가 나오고 있습니다.

형변환을 통해 (n1+n2) 의 값을 double 형으로 형변환을 해주고 똑같이 2 로 나눠주면

결과가 2.50 으로 정상적으로 나오게 됩니다.

세번째 결과도 n1 + n2 의 값을 2.0 이라는 소수로 나눠준다고 명시해주니

두번째와 마찬가지로 2.50 이라는 정상적인 결과를 출력해 줍니다.

이런 결과가 나오는건 정수 / 정수 의 나눗셈에선 절대 소수가 나오지 않기 때문입니다!!

그러니 정수와 정수를 나눠 결과값이 소수여야 한다면

둘중에 하나라도 형변환을 통해 소수로 변경 하거나 상수뒤에 .0 을 붙여서 소수라고 명시해 준다면

손쉽게 원하는 결과를 얻을수 있습니다.

혹시 궁금하신 사항이 있다면 ~ 댓글 주세요 ^^

C에서 정수 나눗셈은 소수점 이하를 버리고(Truncate) 결과를 반환한다.

나눗셈 결과값이 양인 정수는 다음과 같이 버림(Floor)의 결과를 얻는다.

 0/10 = 0 → 0
 1/10 = 0.1 → 0
 10/10 = 1 → 1
 11/10 = 1.1 → 1 

나눗셈 결과값이 음인 정수는 다음과 같이 올림(Ceiling)의 결과를 얻는다.

 -1/10 = -0.1 → 0
 -10/10 = -1 → 1
 -11/10 = -1.1 → -1 

이번 강의에서는 가장 기본적인 연산자에 대해서 배웁니다. 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/) 그리고 나머지(%)에 대해서 알아보도록 하겠습니다.

덧셈

덧셈은 + 기호를 이용합니다. 출력할 때 더한 값을 따로 저장하지 않고 바로 출력할 수도 있으며, 물론 더한 값을 변수에 저장할 수도 있습니다. 

물론 정수와 실수값을 더한 값은 실수형 자료형에 저장해야 합니다.

뺄셈

뺄셈은 - 기호를 이용합니다. 나머지는 위와 동일합니다.

곱셈

곱셈은 * 기호를 이용합니다. 나머지는 위와 동일합니다.

나눗셈

나눗셈은 / 기호를 이용합니다. 일반적으로 정수와 정수끼리 나눗셈을 하면 이 결과 값이 되며, 나머지 값은 버려집니다. 그러나 실수끼리 나눗셈을 하면 정상적으로 나머지값까지 저장됩니다. 

나머지

나머지는 나눗셈을 한 뒤에 남는 수를 의미하며, % 기호를 이용합니다. 예를 들어 10 % 3 의 경우에는 3으로 나눈 후 남은 숫자가 1이므로 나머지는 1이 됩니다.

나머지 연산은 정수와 정수끼리만 가능합니다.

//서론

C/C++ ( 이하 C ) 에서 수치연산을 하다가 보면 너무나도 당연한 부분에서 오류가 쉽게 나곤 한다.

왜냐하면 자료형을 직접 선택해 줘야하는 문제 때문인데

이게 어떨땐 참 편하다가도 어떤 땐 정말 불편한

C가 가진 양날의 검이다.

자료형은 이게 정수형이냐 실수형이냐를 떠나서 좀더 수치해석적으로 사용하는 분야들에서는

혹은 소리와 같이 신호를 현실세계의 아날로그 신호로 복원하는 분야에서는

8, 16, 32, 64 비트중 어떤 것이냐 까지 따지고 들기 때문에 요런 부분을 신경을 잘 써줘야한다.

나누기는 특히나 이 precision(정밀도)이 크게크게 바뀔 수 있는 부분이므로 신경을 써줘야 한다.

//몫과 나머지

나누기 라는 연산은 실제로는 하나지만 구해지는 결과는 몫과 나머지 이므로

이 두가지중 어느 것을 구할지 혹은 두가지 모두를 구할지 사용자가 확실하게 알고 있어야 한다.

실재로 많은 언어에서 modulus function이라고 검색하면 몫을 구해주는 연산자를

reamainder function이라고 검색하면 나머지를 구해주는 연산자를 따로따로 알려준다.

for 문이나 if 문 등을 통해서 연속적인 데이터를 처리할때는 이 부분이 필수적이다.

하지만..

그런 함수를 많이 쓰는건 직관적이지 않고 또 함수의 arguments를 잘못 입력할 경우

공부하고 디버깅을 해야하는 문제가 있다.

그러므로 대부분 "division operator : /"와 "remainder operator operator : %"를 쓴다.

//각설

int main() { int a = 3; int b = 2; int c = a/b; std::cout << "= The result of operation ==" << std::endl; std::cout << "= " << std::endl; std::cout << "= " << c; std::cout << "= " << std::endl; std::cout << "============================" << std::endl; }

간단한 결과를 예측해볼 수 있다. 3/2=1.5 인데 반환값을 정수에 넣었으므로 소수점 이하는 버려지고 1만 남는다.

예상대로 1이 나왔다. 그러면 c의 자료형을 float으로 바꾸면 소수점 아래가 나올까?

int main() { int a = 3; int b = 2; float c = a/b; std::cout << "= The result of operation ==" << std::endl; std::cout << "= " << std::endl; std::cout << "= " << c << std::endl; std::cout << "= " << std::endl; std::cout << "============================" << std::endl; }

이번엔 c만 float으로 바꿔서 출력해보자.

그대로다. 우리는 분명 float에 값을 담았는데 왜 소수점 아래가 없는걸까?

그건 바로 division operator의 연산이 끝났을때부터 소수점 아래가 무시되고 출력되었기 때문이다.

int main() { int a = 3; float b = 2; float c = a/b; std::cout << "= The result of operation ==" << std::endl; std::cout << "= " << std::endl; std::cout << "= " << c << std::endl; std::cout << "= " << std::endl; std::cout << "============================" << std::endl; }

위와 같이 b의 자료형을 바꿔보자.

그러면 우리가 원하는 1.5가 나왔다. 즉 division operator는 좌우에 입력받는 값이 어떤 자료형을 가지느냐에 따라

다른 결과값을 출력으로 내는 것이다.

사실 이렇게만 보면 좀 어이 없어 보인다. 

그런데 문제는 장문의 코드를 짜면서 발생하는데 예컨데 이런 경우다.

int main() { float c = 3 / 2; std::cout << "= The result of operation ==" << std::endl; std::cout << "= " << std::endl; std::cout << "= " << c << std::endl; std::cout << "= " << std::endl; std::cout << "============================" << std::endl; }

이러면 결과가 얼마가 나올까. 당연히 1.5가 나오지 않을까?

놉. 세상에 내 생각대로 당연히 되는건 아무것도 없다. 삼전에 들어가도 손절하고 나오는 세상이다.

실재로 저런 오류가 나면 발견하는데 꽤나 오랜 시간이 걸린다.

C에서는 그냥 1, 2, 3 이렇게 적혀진 숫자들을 int형으로 처리해 버리기 때문에

자칫하면 overflow나 underflow등의 문제에 직면할 수 있다.

아니 그러면 저 간단한 수식 하나 써먹을려고 모든 수치를 일일이 float a; float b; 해야한다는 말인가?

int main() { float c = 3 / 2.; std::cout << "= The result of operation ==" << std::endl; std::cout << "= " << std::endl; std::cout << "= " << c << std::endl; std::cout << "= " << std::endl; std::cout << "============================" << std::endl; }

뭐가 바뀌었는지 찾았는가?

틀린그림찾기의 답은 2뒤에 점이 찍혀있다는 것이다. 이 점은 소수점 아래에 0이 생략되어있다는 의미로

아래와 같이 달라진다.

1  == (int)1

1. == (double)1.0

그리고 이쯤에서 눈치챘겠지만 division operator는 분모의 자료형을 따라가기 때문에

2 뒤에 점을 찍어주는 것 만으로도 충분히 우리가 원하는 수치를 얻을 수 있다.

또 다른 사람이 만든 API 때문에 int를 분모에 사용해야만 한다면

선언된 변수 앞에 (float)혹은 (double)을 붙여서 형변환을 해주는 것으로 쉽게 문제를 해결할 수 있다.

Toplist

최신 우편물

태그