C 언어 나누기 - c eon-eo nanugi

[Quiz] 나눗셈의 출력 결과 조정하기


1. 문제
아래와 같이 사용자에게 값을 입력받아서 나눗셈을 하는 프로그램이 있습니다.

#include <stdio.h> int main() { int num1, num2; printf("정숫값 입력 : "); scanf_s("%d %d", &num1, &num2); if (num2 != 0) { // 2 / 0과 같이 0으로 나누는 것을 방지한다! printf("%d / %d = %d\n", num1, num2, num1 / num2); } return 0; }

위 프로그램을 실행하고 30 6이라고 입력하면 다음과 같이 정상적으로 출력됩니다.

정숫값 입력 : 30 6 30 / 6 = 5 계속하려면 아무 키나 누르십시오 . . .

하지만 1 3이라고 입력하면 아래와 같이 0으로 출력됩니다.

정숫값 입력 : 1 3 1 / 3 = 0 계속하려면 아무 키나 누르십시오 . . .

그래서 위 프로그램을 수정하여 30 6이라고 있을 때는 위와 동일하게 30 / 6 = 5라고 출력되고 1 3처럼 소수점 자릿수가 필요한 결과는 아래와 같이 출력하게 하고 싶습니다. 어떻게 소스를 수정해야 할까요?

정숫값 입력 : 1 3 1 / 3 = 0.333333 계속하려면 아무 키나 누르십시오 . . .

위 소스에서 num1, num2외에 추가적인 변수는 선언을 하면 안 됩니다. 그리고 num1과 num2 변수의 자료형은 int로 유지해야 합니다. printf 함수와 scanf_s 함수 외에 다른 함수를 사용해서도 안됩니다. 그리고 사용자가 7 8이라고 입력했을 때 아래와 같이 출력해야 합니다.

정숫값 입력 : 7 8 7 / 8 = 0.875000 계속하려면 아무 키나 누르십시오 . . .








2. 정답

이 문제의 핵심은 num1 / num2 연산에서 num1과 num2가 정수이기 때문에 정수 연산을 수행한다는 것입니다. 따라서 소수점 자릿수들은 모두 버려지기 때문에 두 정수가 나누어떨어지는 경우에는 문제가 없지만 나누어떨어지지 않는 경우에는 문제가 생기는 것입니다.

단순하게 생각하면 num / num2 연산을 정수 연산이 아닌 실수 연산으로 처리되도록 아래와 같이 형 변환 연산자를 사용하고 연산의 결과는 '%f 형식 지정자'를 사용해서 출력하면 됩니다. 이렇게 하면 1 3이라고 입력했을 때 1 / 3 = 0.333333라고 출력이 됩니다.

// printf("%d / %d = %f\n", num1, num2, (float)num1 / num2); 라고 사용해도 됨! printf("%d / %d = %f\n", num1, num2, num1 / (float)num2);

하지만 위와 같이 코드를 변경하면 30 6이라고 입력해도 아래와 같이 소수점이 출력됩니다. 왜냐하면 '%f 형식 지정자'는 무조건 소수점 여섯 째자리까지 값을 출력하기 때문입니다.

정숫값 입력 : 30 6 30 / 6 = 5.000000 계속하려면 아무 키나 누르십시오 . . .

따라서 위에서 구성한 소스처럼 단순한 형 변환만 사용해서는 정답을 구성하기 어렵습니다.

[ printf 함수의 '%g 형식 지정자'를 사용해서 해결이 가능할까요? ]
이 문제는 printf 함수의 '%g 형식 지정자'를 사용하면 매우 간단하게 해결할 수 있습니다. 왜냐하면 '%g 형식 지정자'의 역할이 위와 같은 문제를 해결하기 위해 만들어졌기 때문입니다. 즉, 위에서 사용했던 코드에서 아래와 같이 %f를 %g로만 수정하면 됩니다.

printf("%d / %d = %g\n", num1, num2, num1 / (float)num2);

위와 같이 수정하면 30 6을 입력했을 때 30 / 6 = 5라고 출력되고 1 3이라고 입력했을 때 1 / 3 = 0.333333이라고 원하는 형태로 출력됩니다. 하지만 이 방법은 7 8을 입력했을 때 문제가 생깁니다. 왜냐하면 '%g 형식 지정자'는 뒤에 0을 무조건 제거하기 때문에 7 / 8 = 0.875000이라고 출력하는 것이 아니라 7 / 8 = 0.875라고 출력이 나옵니다.

아래에 링크한 글은 '%g 형식 지정자'에 대한 설명글이니 한번 읽어보세요.

사실 이 문제가 7 8을 입력했을 때 7 / 8 = 0.875000을 출력하라는 조건이 없었다면 '%g'를 사용해서 너무 쉽게 답이 나오기 때문에 제가 문제에 조건을 하나 더 추가한 것입니다. 즉, 이 조건이 추가되어 '%g' 대신 '%f 형식 지정자'를 사용할 수  밖에 없습니다.

[ 나머지 연산자를 활용해서 구분하자 ]
사실 이 문제는 num1과 num2가 나누어떨어지는 경우에는 정수 연산을 하고 결과는 %d로 출력하면 되고 나누어떨어지지 않는 경우에는 실수 연산을 하고 결과는 %f로 출력하면 됩니다. 따라서 아래와 같이 num1을 num2로 나누었을 때 나머지가 있는지만 체크해서 두 명령을 구분하면 간단하게 답안을 구성할 수 있습니다.

// 나머지가 있으면 실수 연산을 없으면 정수 연산을 한다! if ((num1 % num2) != 0) { printf("%d / %d = %f\n", num1, num2, num1 / (float)num2); } else { printf("%d / %d = %d\n", num1, num2, num1 / num2); }

위 연산에서 (num1 % num2) != 0 조건 수식은 num1 % num2의 값이 0이 나오면 거짓이라는 뜻입니다. 그런데 0이라는 값 자체가 조건 판단에서는 거짓을 의미하기 때문에 num1 % num2 연산의 결과 값을 != 0으로 비교하지 않더라도 num1 % num2 연산의 결과 값이 0이면 거짓을 의미합니다. 따라서 아래와 같이 != 0을 제거하고 사용해도 됩니다.

// 나머지가 있으면 실수 연산을 없으면 정수 연산을 한다! if (num1 % num2) printf("%d / %d = %f\n", num1, num2, num1 / (float)num2); else printf("%d / %d = %d\n", num1, num2, num1 / num2);


[ 완성된 답안 코드 ]
이제 위에서 설명한 내용을 정리해서 완성된 코드를 보여드리면 다음과 같습니다.

#include <stdio.h> int main() { int num1, num2; printf("정숫값 입력 : "); scanf_s("%d %d", &num1, &num2); if (num2 != 0) { if (num1 % num2){ printf("%d / %d = %f\n", num1, num2, num1 / (float)num2); } else { printf("%d / %d = %d\n", num1, num2, num1 / num2); } } return 0; }

P.S
그거 아세요?
제 블로그와 이웃이 되면 C 언어가 쉬워진다는 소문이 있답니다!

C 언어 나누기 - c eon-eo nanugi

그리고 공감을 누르시면 오늘 하루 좋은 일이 생기실 거예요~ :)