코린이의 소소한 공부노트

printf()를 이용한 형식화된 출력 본문

Java

printf()를 이용한 형식화된 출력

무지맘 2021. 12. 12. 01:30

자바를 처음 배울 때 가장 많이 쓰는 메서드인 println()은 ( ) 안의 내용을 화면에 출력하고 줄바꿈을 해준다.

System.out.println("안녕?"); // "안녕?"
System.out.println(10.0/3); // 3.3333333333333335
System.out.println(0x1A); // 26

그런데 이상한 점이 있다.

1) 3.33333..이 아니라 맨 끝이 5다.

2) 소수점 아래 몇째 자리까지 출력할지를 정할 수 없다.

3) 16진수를 넣었는데 10진수가 출력된다.

1번의 경우는 다른 글에서 설명할 예정이고, 2번과 3번은 또 다른 출력 메서드인 printf()로 해결할 수 있다!

 

1. 지시자의 종류와 기본 사용법

지시자는 출력 형식을 결정하는 코드이다. 자바 API[https://docs.oracle.com/javase/7/docs/api/] -> Formatter클래스에서 printf()에 쓸 수 있는 많고 많은 지시자를 볼 수 있다. 우린 그중에서 가장 많이 쓰이는 지시자만 확인해보려 한다.

[그림 006] 지시자의 종류와 사용 예시

1) 지시자는 한 번에 여러 개를 쓸 수 있다. 대신 해당 지시사에 들어가는 값도 지시자와 같은 순서, 같은 개수여야 한다.

2) printf()는 println()과 달리 줄바꿈이 되지 않는다. 줄바꿈을 하고 싶다면 개행문자 '%n'을 넣어주면 된다.

 - 이전 글에서는 '\n'을 많이 썼는데, '%n'이 OS 관계 없이 두루 사용 가능하므로 '%n' 사용을 추천한다.

3) 지시자의 기본 형태는 %플래그길이출력형태이다.

// [ ] 사이에 무언가를 넣어서 출력해보려 한다.
// printf()의 출력은 기본적으로 오른쪽 정렬이다.

// 길이가 5인 정수 출력, 출력할 정수는 123
System.out.printf("[%5d]", 123); // [  123]
// 왼쪽 2자리가 공백으로 출력

// 길이가 5인 정수 출력, 출력할 정수는 123
// - 플래그는 왼쪽 정렬
System.out.printf("[-%5d]", 123); // [123  ]
// 오른쪽 2자리가 공백으로 출력

// 길이가 5인 정수 출력, 출력할 정수는 123
// 공백 자리에 0을 채움
System.out.printf("[%05d]", 123); // [00123]

 

2. 정수 출력 예시

위에서도 잠깐 봤듯이 기본적으로 정수를 출력하고 싶다면 이렇게 하면 된다.

// 10진수 %d
System.out.printf("%d", 9); // 9

// 8진수 %o, 8진수 접두사는 0
System.out.printf("%o", 011); // 11

// 16진수 %x, 16진수 접두사는 0x, A=10, B=11, ..., F=15
System.out.printf("%x", 0x1B); // 1B

진법이 같지 않아도 자동변환이 되기 때문에 위의 예시처럼 꼭 맞춰 쓰지 않아도 된다.

int i = 14; // 10진수 정수
System.out.printf("%d", i); // 14

// 8진수로 출력
System.out.printf("%o", i); // 16

// 16진수로 출력
System.out.printf("%x", i); // e

// 2진수 지시자는 없다.
// 대신 정수를 2진 문자열로 바꿔주는 메서드가 있다.
System.out.printf("%s", Integer.toBinaryString(i)); // "1110"
// 결과는 문자열이므로 지시자는 %s를 사용한다.

위의 예시들을 코드를 가리고 결과만 본다면, 이게 10진수인지 8진수인지 16진수인지 헷갈린다. 숫자의 접두사를 표시하려면 지시자에도 표시를 해야 한다. 자바에서 준비해준 표시는 #이다.

int i = 14; // 10진수 정수

// %와 알파벳 사이에 #을 넣으면 된다.
System.out.printf("%#o", i); // 016
System.out.printf("%#x", i); // 0xe

// 16진수는 x를 대문자로 사용 가능하다.
System.out.printf("%#X", i); // 0XE

위의 코드들을 비교해보면 #이 있고 없고의 차이가 확실하게 보인다.

 

3. 실수 출력 예시

기본적으로 실수를 출력하고 싶다면 다음과 같이 하면 된다.

// %f: 실수를 소수점 이하 6자리까지 출력한다.
System.out.printf("%f", 123.456789f); // 123.456787

float은 정밀도가 7이기 때문에 유효숫자가 123.4567이고, 나머지 숫자는 유효숫자에서 벗어나기 때문에 출력 결과의 맨 마지막 두 자리 87은 의미 없는 숫자이다. 만약 123.456789라는 숫자를 더 정밀하게 표현하고 싶었다면 접두사를 d로 고치거나 지워서 double의 형태로 썼어야 했다.

// %e: 실수를 지수 형식으로 출력한다. 대문자 가능
System.out.printf("%e", 123.456789f); // 1.234568e+02
System.out.printf("%E", 123.456789f); // 1.234568E+02

여기서 가수부가 1.234567이 아닌 1.234568이 된 것은 반올림된 값으로 출력됐기 때문이다. 값 자체는 변하지 않았다.

// %g: %f와 %e 중 더 간략한 형식을 출력한다.
System.out.printf("%g", 123.456789); // 123.457
System.out.printf("%g", 0.00000001); // 1.00000e-08

첫 번째의 경우, %f 형식이 더 간단하다고 판단하고 출력했다. 이 경우 소수점을 포함해서 반올림된 7자리를 출력한다.

두 번째의 경우, %e 형식이 더 간단하다고 판단하고 출력했다.

%g가 왜 이런 결과를 출력했는지 궁금하다면 각 경우마다 %f와 %e 형식을 살펴보면 된다.

[그림 007] 결과 비교

첫 번째의 경우에는 확실히 %f 형식이 더 간단하다는 것을 알 수 있다.

두 번째의 경우에는 결과의 길이 자체는 %f가 짧지만, %f에서 소수점 아래 6자리까지 출력해도 마지막 자리 숫자인 1을 표현할 수 없기 때문에 %e 형식을 취했다. 지수 표현을 했을 때 0이 많은 것도 %e 형식을 선택하는 데 한몫했다.

 

printf()로 실수를 출력할 때 %전체자릿수.소수점이하자릿수f 형식으로 원하는 만큼 자릿수를 설정할 수 있다. 이때 전체 자릿수에 소수점도 포함되고, 마지막에 표시되는 숫자는 반올림돼서 나온다.

// .2: 소수점 이하 2번째까지 출력
System.out.printf("%.2f", 123.456789); // 123.46

// 4.3: 4자리만 출력하는데 소수점 이하 3번째까지
System.out.printf("%4.3f", 123.456789); // 123.457

// 15.10: 전체 15자리 출력. 소수점 이하 10번째까지
// 결과를 [ ]로 감싸서 출력
System.out.printf("[%15.10]f", 123.456789); // [ 123.4567890000]

첫 번째는 가장 많이 사용하는 방식으로, 전체 자릿수를 생략하고 소수점 이하 자릿수만 썼다. 이 경우에는 그냥 소수점 이하만 신경 쓰면 된다.

두 번째는 지시자의 출력 자릿수가 더 짧은 경우이다. 전체 4자리, 소수점 이하 3자리까지 출력을 원하는데, 소수점 이하만 이미 3자리를 차지한다. 정수 부분이 3자리이고, 소수점까지 포함하면 총 7자리가 되어 4자리보다 길어지지만, 그대로 7자리를 출력한다.

세 번째는 지시자의 출력 자릿수가 더 긴 경우이다. 전체 15자리, 소수점 이하 10자리까지 출력을 원하는데, 숫자는 소수점 이하 6자리까지밖에 없으므로 나머지 4자리는 0으로 채운다. 이렇게 되면 정수 부분 3자리 + 소수점 1자리 + 소수 부분 10자리 = 14자리인데, 원하는 것은 15자리이기 때문에 오른쪽 정렬 후 나머지 한자리는 맨 왼쪽에 공백으로 표시된다.

 

4. 문자열 출력 예시

문자열은 %s 지시자를 이용해 출력하면 된다.

String s = "1234567890"; // 숫자 10개로 이루어진 문자열
System.out.printf("[%s]", s);		// [1234567890]
System.out.printf("[%15s]", s);		// [     1234567890]
System.out.printf("[%-15s]", s);	// [1234567890     ]
System.out.printf("[%.5s]", s);		// [12345]
System.out.printf("[%5s]", s);		// [1234567890]

첫 번째는 그냥 문자열을 있는 대로 출력한 것이다.

두 번째는 길이가 15인 문자열을 출력하는 것으로, 오른쪽 정렬 후 왼쪽에 5개의 공백이 생겼다.

세 번째는 길이가 15인 왼쪽 정렬 문자열을 출력하는 것으로, 오른쪽에 5개의 공백이 생겼다.

네 번째는 소수점 이하 자릿수를 쓰듯 부분 출력을 하는 것으로, 문자열 처음부터 5개의 문자만 잘라서 출력됐다.

마지막은 길이가 5인 문자열 s를 출력하는 것으로, 실수에서 지시자의 출력 자릿수가 짧았을 때 그냥 다 출력했던 것처럼 문자열 s 전체가 출력된다.