Entrada e Saı́da:
Lendo Dados do Teclado
14
14.7
Formatando a saı́da
Os valores de saı́da normalmente são produzidos sem formatação. Em particular, os valores
numéricos exibem o número de casas decimais resultantes das operações sobre eles realizadas. Assim a expressão 1f/21 resulta no valor 0.04761905 (o número de casas decimais e
o arredondamento depende do valor resultante e do tipo primitivo utilizado).
Em várias ocasiões precisamos formatar a saı́da para, por exemplo, imprimir valores
com um número predeterminado de casas decimais. A linguagem Java oferece um série de
alternativas para produzir valores de saı́da formatados.
14.7.1
O método printf
A classe PintStream possui o método printf que permite a formatação de uma cadeia
de caracteres segundo diretivas de formatação. Este método recebe como argumentos uma
cadeia de caracteres contendo as diretivas de formatação e os objetos que serão impressos
segundo essas diretivas.
PrintStream printf(String formato, Object arg ...) Produz a saı́da correspondente aos objetos arg (as reticências indicam que podem ser fornecidos vários objetos)
formatados segundo as diretivas em formato.
A cadeia de caracteres que especifica a formatação contém caracteres fixos, que serão
impressos como aparecem, e diretivas de formatação. As diretivas de formatação são indicadas pelo caractere %. Para cada diretiva de formatação deve existir um argumento.
Exceto quando a diretiva indica um argumento especı́fico, a primeira diretiva é aplicada
2
Entrada e Saı́da: Lendo Dados do Teclado
ao primeiro argumento, a segunda diretiva é aplicada ao segundo argumento, e assim por
diante. Os argumentos excedentes simplesmente não são impressos.
Exemplo 14.1. A cadeia "Exemplo %f de cadeia %,d %.3f de formatacao" possui
três diretivas de formatação: %f, %,d e %.3f. Os demais caracteres são impressos da
forma como aparecem. Se esta cadeia for usada para formatar os valores 45.6721 e 2367,
como em:
System.out.printf("Exemplo %f de cadeia %,d %.3f de formatacao",
45.6721, 2367, 45.6721);
teremos a seguinte saı́da:
Exemplo 45,672100 de cadeia 2.367 45,672 de formatacao
Os caracteres fixos, incluindo os espaços, são impressos exatamente do modo como
aparecem na cadeia de formatação. Os valores dos argumentos são formatados segundo a
diretiva aplicada a cada um deles. Ao primeiro argumento é aplicada a diretiva %f, que
apenas faz com que o valor seja impresso no formato de um número real; A diretiva %,d
é aplicada ao segundo argumento, formatando-o com o separador de milhar, e a diretiva
%.3f é aplicada ao terceiro argumento, formatando-o com três casas decimais. Para cada diretiva deve existir um argumento de um tipo compatı́vel com o especificado
na diretiva. Se são fornecidos mais argumentos que os especificados nas diretivas, os argumentos adicionais são ignorados. Ocorre um erro (da classe IllegalFormatException) se
os argumentos não são compatı́veis ou se a quantidade de argumentos é menor que o especificado na diretiva. A quantidade de argumentos pode ser zero se a cadeia de formatação
não contiver diretivas.
Diretiva de formatação
Cada diretiva de formatação especifica uma forma de conversão, usada para transformar o
argumento em uma cadeia de caracteres cujo conteúdo corresponda ao valor do argumento.
A estrutura de uma diretiva de formatação é a seguinte:
hDiretivai ::= % [ hPosArgi ] [ hApresi ] [ hTamanhoi ] [ hPrecisãoi ] hConversãoi
onde hPosArgi indica a posição do argumento ao qual a diretiva é aplicada, hApresi indica
a forma de apresentação do argumento (alinhamento, uso de sinal, etc. ), hTamanhoi indica
a quantidade mı́nima de caracteres usadas na formatação, hPrecisãoi indica a quantidade
de casas decimais e hConversãoi indica a conversão a ser aplicada ao argumento. Todos os
termos, exceto o indicador de conversão e caractere ‘%’, são opcionais.
14.7 Formatando a saı́da
3
Tabela 14.1. Caracteres de conversão de uma diretiva de formatação
caractere
‘b’ ‘B’
classe
Geral
‘h’ ‘H’
Geral
‘s’ ‘S’
Geral
‘c’
‘d’
‘o’
‘x’ ‘X’
‘f’
‘e’ ‘E’
‘g’ ‘G’
Caractere
Inteiro
Inteiro
Inteiro
Real
Real
Real
‘a’ ‘A’
Real
‘t’ ‘T’
‘%’
‘n’
Data/Hora
Percentual
Fim de linha
descrição
Se o argumento é nulo, então o resultado é a cadeia "false".
Se o argumento representa um valor booliano, então o resultado
é a cadeia correspondente a esse valor. Nos demais casos, o
resultado é a cadeia "true".
Se o argumento é nulo, então o resultado é "null". Em caso
contrário, o resultado é um inteiro correspondente ao código da
tabela hash que identifica o objeto.
Se o argumento é nulo resulta na cadeia "null". Se o argumento
implementa um objeto formatável (interface Formattable),
então o resultado é a chamada arg.toFormat(). Nos demais
casos resulta na conversão do argumento em uma cadeia de caracteres (usando-se o método arg.toString() se arg for um
objeto).
Resultado formatado como um caractere Unicode.
Resultado formatado como um inteiro.
Resultado formatado como um inteiro octal .
Resultado formatado como um inteiro hexadecimal.
Resultado formatado como um real em notação decimal.
Resultado formatado como um real em notação cientı́fica.
Resultado formatado como um real em notação decimal ou em
notação cientı́fica dependendo da precisão ou do valor após o
arredondamento.
Resultado formatado como hexadecimal em notação exponencial.
Resultado formatado como data/tempo.
Produz o literal ‘%’ (‘\u0025’).
Produz um caractere de fim de linha.
4
Entrada e Saı́da: Lendo Dados do Teclado
Indicador de conversão
A conversão do argumento é indicada pelos caracteres de conversão da Tabela 14.1:
Exemplo 14.2. O programa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.*;
class C14ExemploF2 {
public static void main(String[] arg) {
boolean res = true;
System.out.printf("%b %B%n", null, res);
Scanner tec = new Scanner(System.in);
System.out.printf("%h %H %n", tec, null);
Float objF = new Float(230.32);
System.out.printf("%s %S %n", objF, tec);
char c = ’d’;
System.out.printf("%c %c %n", c, ’a’);
int numI = 1234;
System.out.printf("%d %o %X %n",numI, numI, numI);
double numR = 1234.5677;
System.out.printf("%f %e %G %A %n",numR, numR, numR, numR);
System.out.printf("fixo%%");
}
}
produz a seguinte saı́da:
false TRUE
3e25a5 NULL
230.32 JAVA.UTIL.SCANNER[DELIMITERS=\P{JAVAWHITESPACE}+][POSITION=0]
[MATCH VALID=FALSE][NEED INPUT=FALSE][SOURCE CLOSED=FALSE]
[SKIPPED=FALSE][GROUP SEPARATOR=\.][DECIMAL SEPARATOR=\,]
[POSITIVE PREFIX=][NEGATIVE PREFIX=\Q-\E][POSITIVE SUFFIX=]
[NEGATIVE SUFFIX=][NAN STRING=\Q?\E][INFINITY STRING=\Q?\E]
d a
1234 2322 4D2
1234,567700 1.234568e+03 1234.57 0X1.34A45532617C2P10
fixo%
Os comandos System.out.printf ilustram algumas das conversões da Tabela 14.1. O
salto de linha é produzido pela diretiva %n. O valor 3e25a5 produzido pelo comando da linha 7 corresponde ao código da tabela hash que identifica o objeto criado na linha 6. O valor
230.32 produzido pelo comando da linha 9 corresponde ao resultado de objF.toString() e
o restante da linha impressa, de JAVA.UTIL até STRING=\Q?\E], corresponde ao resultado
de tec.toString(). A letra P produzida pela diretiva %A no comando da linha 15 indica
o expoente da notação real hexadecimal. As descrições da Tabela 14.1 são suficientes para
a compreensão das demais conversões deste programa. 14.7 Formatando a saı́da
5
Posição do argumento
As diretivas podem indicar o argumento ao qual serão aplicadas de modo explı́cito, fornecendo a posição do argumento como um inteiro seguido do caractere $. O primeiro
argumento é indicado por 1$, o segundo por 2$, e assim por diante. Pode-se usar o caractere < para indicar que a diretiva é aplicada ao mesmo argumento da diretiva anterior.
Quando não existe a indicação explı́cita de um argumento, então considera-se que existe
uma indicação implı́cita que começa com o primeiro argumento. A primeira diretiva com
indicação implı́cita refere-se sempre ao primeiro argumento, a segunda refere-se sempre ao
segundo argumento, e assim por diante.
Exemplo 14.3. O comando
System.out.printf("%3$f %f %4$d %d %<d", 10.0, 20, 30.0, 40);
produz a seguinte saı́da:
30,000000 10,000000 40 20 20
A primeira diretiva contém a indicação explı́cita do argumento ao qual é aplicada (o
terceiro) e produz a saı́da 30,000000. A segunda diretiva é aplicada ao primeiro argumento porque é a primeira diretiva sem indicação explı́cita de argumento; produz a saı́da
10,000000. A terceira diretiva é aplicada ao quarto argumento e produz a saı́da 40. A
quarta diretiva é aplicada ao segundo argumento porque é a segunda diretiva sem indicação
explı́cita de argumento; produz a saı́da 20. A última diretiva indica explicitamente que
deve ser aplicada ao mesmo argumento que a diretiva anterior. Indicador de tamanho
O tamanho mı́nimo da saı́da pode ser indicado por um inteiro positivo. Se o valor após a
conversão possuir mais caracteres que o mı́nimo, a limitação de tamanho não será aplicada.
Se possuir menos caracteres, então serão usados caracteres adicionais. Geralmente são
adicionados espaços à esquerda, mas esse comportamento pode ser mudado pelo indicador
de apresentação.
Precisão
A precisão é indica por um ponto seguido de um inteiro.
Classe geral. Para as conversões b, B, h, H, s e S a precisão define o total de caracteres da
saı́da.
Classe real. Para as conversões e, E e F a precisão indica o número de casas após o
ponto decimal. Para g e G, indica o número total de dı́gitos na magnitude após o
arredondamento. Para a e A a precisão não deve ser especificada.
6
Entrada e Saı́da: Lendo Dados do Teclado
Demais classes. A precisão não deve ser especificada para caracteres (c), inteiros (d, o, x
e X), data/hora (t e T), caractere % e fim de linha (\n).
Indicador de apresentação
O indicador de apresentação é usado para modificar a aparência do resultado, sendo aplicado a alguns tipos de conversão.
‘-’. Produz saı́das alinhadas à esquerda. Aplicado às conversões das classes geral, caractere, inteiro, real e data/hora.
‘#’. Produz o resultado em modo alternativo. Aplicado a conversões das classes geral,
inteiro (apenas para ‘o’, ‘x’ e ‘X’) e real.
‘+’. Produz sempre o sinal do número. Aplicado para conversões das classes real e inteiro
(apenas para ‘d’, quando o objeto for de um tipo primitivo, ou para ‘d’, ‘o’, ‘x’
e ‘X’, quando o argumento for da classe BigInteger).
‘ ’. Inclui espaços frontal para valores positivos. Aplicado a conversões das classes real
e inteiro (apenas para ‘d’, quando o objeto for de um tipo primitivo, ou para ‘d’,
‘o’, ‘x’ e ‘X’, quando o argumento for da classe BigInteger).
‘0’. Inclui zeros à esquerda para atingir o tamanho mı́nimo. Aplicado a conversões das
classes real e inteiro.
‘,’. Inclui separadores de grupos (depende da localização do ambiente). Aplicado a
conversões das classes inteiro (apenas para ‘d’) e real (apenas para ‘e’, ‘E’, ‘f’,
‘g’ e ‘G’).
‘(’. Coloca números negativos entre parênteses. Aplicado a conversões da classes real
(apenas para ‘e’, ‘E’, ‘f’, ‘g’ e ‘G’) e inteiro (apenas para ‘d’, quando o objeto
for de um tipo primitivo, ou para ‘d’, ‘o’, ‘x’ e ‘X’, quando o argumento for da
classe BigInteger).
Exemplo 14.4. A tabela a seguir mostra o resultado do comando System.out.printf
para diferentes argumentos. As variáveis estão definidas como:
String frase = "A Josefa pode ficar brava";
double num
= 234.678591;
int numI = 7364;
int numN = -571;
14.7 Formatando a saı́da
argumentos
("%.13s", frase)
7
saı́da resultante
A Josefa pode
("%20.13s", frase)
A Josefa pode
("%-20.13sTxt%n", frase)
A Josefa pode
("%.3f", num)
234,679
("%4.3f", num)
234,679
("% 4.3f", num)
("%10.3f", num)
234,679
234,679
("%010.3f", num)
000234,679
("%+10.3f", num)
("%.0f", num)
+234,679
235
("%.9f", num)
234,678591000
("%15.9f", num)
234,678591000
("%x %#x",numI, numI)
1cc4 0x1cc4
("%,d",numI)
7.364
("%d %(d",numN, numN)
-571 (571)
Txt
O conteúdo de frase é limitado a 13 caracteres.
Após a limitação do conteúdo de frase, são
incluı́dos espaços para completar os 20 caracteres de tamanho mı́nimo.
A saı́da continua com 20 caracteres, mas o
conteúdo é alinhado à esquerda.
O valor é produzido com 3 casas decimais,
havendo arredondamento.
O tamanho mı́nimo não tem efeito porque
a conversão e precisão resultam em uma
saı́da com 7 casas decimais.
É incluı́do um espaço frontal.
São incluı́dos 3 espaços iniciais para completar o tamanho mı́nimo de 10 caracteres.
Zeros são usados para completar o tamanho
mı́nimo.
O sinal é sempre produzido.
O valor resultante é produzido sem casas
decimais.
São incluı́dos zeros à direita para completar
o número de 9 casas decimais.
São incluı́dos zeros à direita para completar
as 9 casas decimais, e espaços à esquerda
para completar o tamanho mı́nimo de 15
caracteres.
A segunda diretiva imprime numI na forma
alternativa, indicando que se trata de um
valor hexadecimal.
A saı́da é produzida com separador de milhar.
A segunda diretiva produz a saı́da entre
parênteses.
As situações que a tabela ilustra mostram que a saı́da resultante é produzida em etapas.
Primeiro ocorre a conversão do argumento, seguindo-se a definição da precisão e por último
o tamanho mı́nimo é considerado. A formatação para atender o indicador de apresentação
ocorre por último. 14.7.2
Formatando datas
Os caracteres t e T indicam a conversão de datas e horas, expressas como objetos da classe
Date ou Calendar ou como valores do tipo long. O formato a ser utilizado na conversão
é indicado por um caractere adicional. A Tabela 14.7.2 mostra alguns dos caracteres que
podem ser usados.
8
Entrada e Saı́da: Lendo Dados do Teclado
Tabela 14.2. Caracteres para formatação de data e hora
‘H’
‘k’
‘I’
‘l’
‘M’
‘S’
‘p’
‘B’
‘b’ ’h’
‘A’
‘a’
‘C’
‘Y’
‘y’
‘j’
‘m’
‘d’
‘e’
‘R’
‘T’
‘r’
‘D’
Hora do dia no formato 24h, com dois dı́gitos.
Hora do dia no formato 24h.
Hora do dia no formato 12h, com dois dı́gitos.
Hora do dia no formato 12h.
Minutos com dois dı́gitos (00-59).
Segundos com dois dı́gitos (00-60).
Perı́odo como am ou pm.
Nome completo do mês (depende da localização)
Nome abreviado do mês (depende da localização)
Nome completo da semana.
Nome abreviado da semana.
Século. Corresponde ao ano com quatro dı́gitos dividido por 100 (formatado com dois dı́gitos).
Ano com quatro dı́gitos.
Ano com dois dı́gitos.
Dia do ano com três dı́gitos 001 a 366.
Mês com dois dı́gitos 01 a 13.
Dia do mês com dois dı́gitos, 01 a 31.
Dia do mês, 1 a 31.
Formato 24h correspondendo a "%tH:%tM"
Formato 24h correspondendo a "%tH:%tM:%tS"
Formato 12h correspondendo a "%tI:%tM:%tS %Tp"
Data formatada como "%tm/%td/%ty"
14.8 Usando números com formato fixo
9
Exemplo 14.5. O programa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.*;
import java.util.Calendar.*;
class C14ExemploF5 {
public static void main(String[] arg) {
Date dt = new Date();
Calendar data = Calendar.getInstance();
System.out.println(dt);
System.out.printf("%tH horas de %<tA %n",dt);
System.out.printf("%tD %n",dt);
System.out.printf("%tT %n",dt);
System.out.printf("hoje: %td de %<tB de %<tY %n",data);
System.out.printf("%tD %n",data);
System.out.printf("%tT %n",data);
}
}
produz a seguinte saı́da:
Sun Dec 17 23:38:34 BRST 2006
23 horas de Domingo
12/17/06
23:38:34
hoje: 17 de Dezembro de 2006
12/17/06
23:38:34
Os comandos das linhas 5 e 6 criam objetos Date e Calendar refletindo a data e
hora do momento em que foram criados. O comando de impressão da linha 7 mostra a
representação do objeto dt como uma cadeia de caracteres. Os comandos das linhas 8 a
13 ilustram algumas das diretivas de formatação de datas aplicadas aos objetos dt e data.
Os comandos das linhas 8 e 11 usam o caractere < para indicar que a diretiva é aplicada
ao mesmo argumento que a diretiva anterior. 14.8
Usando números com formato fixo
Em algumas situações é necessário trabalhar com números de formato fixo, considerandoos, por exemplo, como se tivessem todos apenas duas casas decimais. Nestes casos, a
formatação produzida pelo método printf é de pouca valia porque não afeta o modo como
os números são armazenados. Podemos, entretanto usar a classe BigDecimal que permite
representar números reais de tamanho e precisão arbitrárias.
Os números representados por objetos da classe BigDecimal são determinados por um
valor inteiro, representando o número sem casas decimais, e uma escala, representando a
10
Entrada e Saı́da: Lendo Dados do Teclado
quantidade de casas decimais que deve existir após o ponto decimal. Assim, um número
BigDecimal com magnitude m e escala e representa o valor m × 10−e . Os objetos da classe
BigDecimal são criados fornecendo-se como argumento o valor correspondente ao número:
new BigDecimal(4.547). Cria o objeto correspondente ao número 4.547.
new BigDecimal("4.583"). Cria o objeto correspondente ao número 4.583.
new BigDecimal(53.5/3). Cria o objeto que corresponde ao resultado da operação
53.5/3.
Quando um objeto BigDecimal é criado sua escala assume o valor necessário para
representá-lo. Nos dois primeiros exemplos acima a escala é 3. Já no terceiro exemplo o
objeto é criado com uma escala 48, pois representa o número
17.833333333333332149095440399833023548126220703125.
14.8.1
Determinando a escala
Para criar um objeto com um número predefinido de casas decimais devemos explicitamente
determinar sua escala usando o método setScale. Este método não modifica o objeto que
o executa, apenas retorna um novo objeto que corresponde àquele que executa o método,
com o número especificado de casas decimais.
BigDecimal nx = (new BigDecimal(4.547)).setScale(5). Cria o objeto correspondente ao número 4.54700.
ny = ny.setScale(5). Armazena em ny um novo objeto, que corresponde a ny (antes
da atribuição) com 5 casas decimais.
nr = ny.setScale(3). Armazena em nr o objeto que corresponde a ny com 3 casas
decimais. O objeto ny permanece inalterado.
14.8.2
Polı́tica de arredondamento
Quando se determina a escala de um objeto BigDecimal, ocorre um erro (da classe ArithmeticException)
se for necessário arredondar o valor resultante e a polı́tica de arredondamento não estiver
especificada. Para evitar o erro devemos determinar a escala informando também a polı́tica
de arredondamento a ser adotada.
A classe BigDecimal possui variáveis estáticas que indicam a polı́tica de arredondamento:
14.8 Usando números com formato fixo
ROUND DOWN
ROUND UP
ROUND HALF DOWN
ROUND HALF UP
ROUND HALF EVEN
14.8.3
11
Arredonda para baixo. Exemplo: 1, 239 → 1, 23.
Arredonda para cima. Exemplo: 1, 232 → 1, 24.
Arredonda para o vizinho mais próximo. Se os vizinhos forem
eqüidistantes arredonda para baixo. Exemplo 1, 239 → 1, 24,
1, 234 → 1, 23 e 1, 235 → 1, 23.
Arredonda para o vizinho mais próximo. Se os vizinhos forem
eqüidistantes arredonda para cima. Exemplo 1, 239 → 1, 24,
1, 234 → 1, 23 e 1, 235 → 1, 24.
Arredonda para o vizinho mais próximo. Se os vizinhos forem
eqüidistantes arredonda para o vizinho par. Exemplo 1, 239 →
1, 24, 1, 234 → 1, 23 e 1, 235 → 1, 24, 1, 225 → 1, 22.
Operações com BigDecimal
As operações envolvendo objetos BigDecimal devem ser realizadas através dos métodos da
classe BigDecimal. Deve-se observar que o resultado das operações é um novo objeto.
BigDecimal add(BigDecimal b). Quando executado por a retorna um novo objeto que
corresponde a a + b. A escala é igual à maior dentre as escalas de a e b.
BigDecimal subtract(BigDecimal b). Quando executado por a retorna um novo objeto
que corresponde a a - b. A escala é igual à maior dentre as escalas de a e b.
BigDecimal multiply(BigDecimal b). Quando executado por a retorna um novo objeto
que corresponde a a * b. A escala é igual à soma das escalas de a e b.
BigDecimal divide(BigDecimal b, RoundingMode m). Quando executado por a retorna um novo objeto que corresponde a a / b. A escala é igual à diferença entre
as escalas de a e b. O segundo argumento define a polı́tica de arredondamento e é
necessário nos casos em que o resultado não pode ser calculado de modo exato com
o número de casas decimais da escala resultante.
BigDecimal pow(int n). Quando executado por a retorna um novo objeto que corresponde a an . O novo objeto possui a escala necessária para armazenar o resultado
exato.
Pode-se obter o valor de um tipo primitivo correspondente ao conteúdo de um objeto
BigDecimal através dos métodos doubleValue, longValue e intValue. Para se obter a
representação do número como uma cadeia de caracteres deve-se usar o método toString.
A referência ao próprio objeto também pode ser usada em comandos de impressão.
Exemplo 14.6. O programa abaixo lê uma seqüência de 5 valores reais, considerando-os
todos com duas casas decimais. Se o valor tiver mais de duas casas decimais deverá ser
12
Entrada e Saı́da: Lendo Dados do Teclado
arredondado. Após a leitura o programa imprime todos os valores lidos divididos pela
constante 2.23.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.math.*;
import java.util.*;
class C14ExemploF6 {
public static void main(String[] arg) {
Scanner tec = new Scanner(System.in);
BigDecimal[] valor = new BigDecimal[5];
int ard = BigDecimal.ROUND_HALF_EVEN;
BigDecimal fator = new BigDecimal(2.23).setScale(2,ard);
for (int i=0; i < 5; i++) {
valor[i] = (new BigDecimal(tec.nextDouble())).setScale(2,ard);
}
for (int i=0; i < 5; i++) {
System.out.print(valor[i].divide(fator,ard)+" ");
}
}
}
Os números são armazenados em um vetor de BigDecimal (linhas 9 a 11). Se os valores
lidos forem 2.34, 120.21, 200, 100.98 e 88.44, então o programa produz a seguinte saı́da:
1.05 53.91 89.69 45.28 39.66
Se os valores fosse armazenados apenas como double, a saı́da produzida seria:
1.0493273542600896 53.90582959641255 89.68609865470852
45.28251121076234 39.65919282511211
Para melhorar a legibilidade do programa a referência à polı́tica de arredondamento
é feita através da variável ard, declarada na linha 7. Observe que se usássemos a declaração import static java.math.BigDecimal.* poderı́amos usar ROUND HALF EVEN
diretamente.