HOWTO · C
C에서 과학적 표기법으로 숫자 인쇄
이 기사에서는 C로 과학적 표기법으로 숫자를 인쇄하는 방법을 소개합니다.
이 페이지의 내용
printf에서 %e 또는 %E 변환을 사용하면 부동소수점 값을 과학적 표기법으로 표시할 수 있습니다. 소문자 변환은 소문자 지수 표시자를, 대문자 변환은 대문자 지수 표시자를 출력합니다. %.3e처럼 정밀도를 지정하면 가수의 소수점 뒤에 표시할 자릿수를 정할 수 있습니다.
다음 예제를 실행해 보세요:
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
#include <stdio.h>
int main(void) {
double values[] = {123456.789, -0.000012345};
printf("lowercase: %.3e\n", values[0]);
printf("uppercase: %.3E\n", values[1]);
return 0;
}
C에서 과학적 표기법이 작동하는 방식
과학적 표기법은 0이 아닌 값을 가수와 10의 거듭제곱의 곱으로 나타냅니다. 가수에는 소수점 앞에 0이 아닌 숫자 하나가 오고, 지수는 소수점이 얼마나 이동하는지를 나타냅니다. 예를 들어 123456은 1.23456 × 10^5로, 0.0000123은 1.23 × 10^-5로 쓸 수 있습니다.
이 표기법은 값이 표시되는 방식을 바꾸지만, 내부의 float 또는 double이 값을 저장하는 방식은 바꾸지 않습니다. 이진 부동소수점 형식은 정밀도가 유한하므로 많은 십진 소수가 메모리에서 근삿값으로 저장됩니다. 더 많은 자릿수를 출력하면 저장된 근삿값을 더 자세히 볼 수 있지만, 저장된 값의 정밀도가 높아지는 것은 아닙니다.
printf로 과학적 표기법 출력하기
e와 E 변환은 double 인수를 과학적 표기법으로 형식화합니다. 지수 표시자의 대소문자는 변환 지정자를 따릅니다. %e는 e를, %E는 E를 사용합니다. 지수에는 부호가 포함되며, 구현은 지수를 나타내기에 충분한 자릿수를 출력합니다. 고정소수점 표기와 비교하려면 %f를 사용하세요. POSIX fprintf 명세에서 e와 E 변환 및 정밀도 동작을 확인할 수 있습니다.
앞의 예제에서 %.3e와 %.3E는 각각 가수의 소수점 뒤에 세 자리를 표시합니다. 형식화된 숫자에는 값의 부호도 그대로 포함됩니다. 고정소수점 출력으로 읽기 어려운 크기의 값도 과학적 표기법을 사용하면 가수는 간결하게 유지하고 지수로 크기를 나타낼 수 있습니다.
이 변환은 double 인수를 받습니다. printf에 전달된 float은 double로 승격되지만, 정수는 그렇지 않습니다. 정수 값을 과학적 표기법으로 형식화하려면 예를 들어 (double)count처럼 명시적으로 변환한 다음 %e 또는 %E를 사용하세요. 큰 정수가 double로 표현할 수 있는 정밀도를 넘으면 변환 과정에서 하위 자릿수를 잃을 수 있습니다.
소수점 뒤 자릿수 제어하기
%e와 %E에서 정밀도는 전체 유효 숫자 수가 아니라 소수점 뒤 자릿수를 의미합니다. 따라서 %.2e는 가수의 소수부 두 자리를 출력하며, 보통 전체 유효 숫자는 세 자리입니다. 정밀도를 생략하면 기본값은 소수점 뒤 여섯 자리입니다. 표시할 때 요청한 정밀도에 맞춰 반올림하지만, 저장된 값은 바뀌지 않습니다. POSIX fprintf 명세에서 정밀도 규칙과 기본값 여섯 자리를 확인할 수 있습니다.
애플리케이션에 필요한 표시 형식이나 교환 형식에 맞춰 정밀도를 선택하세요. 출력 자릿수를 늘려도 십진 문자열이 이진 부동소수점 값을 정확히 나타낸다는 보장은 없습니다. 특정 유효 숫자 수가 필요하다면 정밀도를 정할 때 가수의 첫 번째 숫자도 고려하세요.
과학적 표기법 문자열을 안전하게 형식화하기
형식화한 숫자를 저장하거나 다른 함수에 전달해야 한다면 버퍼 용량을 지정하는 snprintf를 사용하세요. 용량에는 끝의 널 문자를 위한 공간도 포함됩니다. snprintf는 널 문자를 제외하고 기록했을 문자 수를 반환합니다. 반환값이 버퍼 용량 이상이면 출력이 잘린 것입니다. 음수 반환값은 형식화 오류를 뜻합니다. POSIX fprintf 명세에서 snprintf의 반환값과 잘림 동작을 확인할 수 있습니다.
다음은 독립적으로 실행할 수 있는 예제입니다:
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
#include <stdio.h>
int main(void) {
double measurement = 0.000012345;
char text[64];
int length = snprintf(text, sizeof text, "%.3e", measurement);
if (length < 0) {
puts("formatting error");
return 1;
}
if ((size_t)length >= sizeof text) {
puts("buffer too small");
return 1;
}
printf("value: %s\n", text);
return 0;
}
snprintf는 사용 가능한 용량을 넘지 않게 기록하며, 용량이 0보다 크면 버퍼를 널 문자로 끝냅니다. 버퍼에 형식화 결과가 완전히 들어갔다고 판단하기 전에 반환값을 확인하세요. 버퍼 크기가 충분하다고 보장할 수 없다면 경계가 없는 sprintf는 피하세요.
사용자 정의 과학적 표기법 함수를 작성해야 할까요?
대개는 그렇지 않습니다. %e와 %E는 C 라이브러리의 형식화 규칙에 따라 가수, 지수, 부호, 반올림 및 0 값을 이미 처리합니다. 직접 변환 함수를 작성한다면 0을 별도로 처리하고, 1보다 작은 값과 10 이상인 값을 모두 정규화해야 합니다. 음수, 반올림으로 가수가 바뀌는 경우, 숫자 형식의 한계도 고려해야 합니다. 양수 값을 10으로 나누기만 하는 반복문으로는 이런 경우를 올바르게 처리할 수 없습니다.
화면에 바로 표시할 때는 printf를, 용량이 제한된 문자열을 만들 때는 snprintf를 사용하세요. 표준 변환으로 표현할 수 없는 특정 형식이 필요할 때만 사용자 정의 형식화 함수를 작성하고, 입력 범위 전체에서 어떻게 동작해야 하는지 정의한 뒤 확인하세요. 일반적인 과학적 표기법에는 표준 변환이 더 짧고 오류가 발생할 여지도 적습니다.