HOWTO · C
Imprimir Números em Notação Científica em C
Este artigo apresenta como imprimir números em notação científica em C
Nesta página
Use a conversão %e ou %E de printf para exibir um valor de ponto flutuante em notação científica. A conversão em minúsculas imprime o marcador do expoente em minúsculas; a conversão em maiúsculas o imprime em maiúsculas. Uma precisão como %.3e define o número de dígitos após o separador decimal no significando.
Execute este exemplo:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
#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;
}
Como funciona a notação científica em C
A notação científica representa um valor diferente de zero como um significando multiplicado por uma potência de dez. O significando tem um dígito diferente de zero antes do separador decimal; o expoente indica quantas casas a vírgula se desloca. Por exemplo, 123456 pode ser escrito como 1.23456 × 10^5, enquanto 0.0000123 pode ser escrito como 1.23 × 10^-5.
Essa notação muda a forma como um valor é exibido, mas não a maneira como o float ou o double subjacente o armazena. Os tipos de ponto flutuante binário têm precisão finita, por isso muitas frações decimais são aproximações na memória. Imprimir mais dígitos pode revelar melhor a aproximação armazenada; isso não aumenta a precisão do valor armazenado.
Imprima notação científica com printf
As conversões e e E formatam um argumento double em notação científica. A letra do marcador de expoente acompanha a conversão: %e usa e e %E usa E. O expoente inclui um sinal, e as implementações imprimem dígitos suficientes para representá-lo. Use %f quando quiser comparar com a notação de ponto fixo. A especificação POSIX de fprintf define as conversões e e E e o comportamento da precisão.
No exemplo de abertura, %.3e e %.3E mostram três dígitos após o separador decimal no significando. O sinal do valor continua fazendo parte do número formatado. Para valores cuja magnitude torna difícil ler a saída em ponto fixo, a notação científica mantém o significando compacto e deixa o expoente indicar a escala.
A conversão espera um argumento double. Um float passado para printf é promovido a double, mas um inteiro não. Para formatar um valor inteiro em notação científica, converta-o explicitamente, por exemplo com (double)count, e use %e ou %E. Inteiros grandes podem perder dígitos menos significativos na conversão se ultrapassarem a precisão representável por double.
Controle o número de dígitos após o separador decimal
Para %e e %E, a precisão conta os dígitos após o separador decimal, não o total de algarismos significativos. Assim, %.2e imprime dois dígitos fracionários no significando, geralmente três algarismos significativos ao todo. Se você omitir a precisão, o padrão é de seis dígitos após o separador decimal. O valor é arredondado para exibição conforme a precisão solicitada; o valor armazenado não muda. A especificação POSIX de fprintf descreve a regra de precisão e o padrão de seis dígitos.
Escolha a precisão de acordo com a exibição ou o formato de intercâmbio de que sua aplicação precisa. Imprimir mais dígitos não garante que a string decimal represente exatamente o valor de ponto flutuante binário. Se você precisa de um número específico de algarismos significativos, considere o dígito inicial do significando ao escolher a precisão.
Formate strings em notação científica com segurança
Quando for necessário armazenar o número formatado ou passá-lo a outra função, use snprintf com a capacidade do buffer. Essa capacidade inclui o caractere nulo de terminação. A função retorna o número de caracteres que teria escrito, sem contar esse terminador; um valor de retorno maior ou igual à capacidade indica que a saída foi truncada. Um valor de retorno negativo indica um erro de formatação. A especificação POSIX de fprintf define o valor de retorno de snprintf e o comportamento de truncamento.
Execute este exemplo independente:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
#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 escreve no máximo até a capacidade disponível e termina o buffer com um caractere nulo quando sua capacidade é maior que zero. Verifique o valor de retorno antes de tratar o buffer como um resultado formatado completo. Evite sprintf sem limite quando não houver garantia de que o buffer terá espaço suficiente.
Vale a pena escrever uma função própria para notação científica?
Em geral, não. %e e %E já tratam o significando, o expoente, o sinal, o arredondamento e o valor zero de acordo com as regras de formatação da biblioteca de C. Uma conversão escrita à mão precisa tratar o zero separadamente e normalizar valores menores que um, assim como valores iguais ou maiores que dez. Também precisa considerar valores negativos, arredondamentos que alterem o significando e os limites do tipo numérico. Um laço que apenas divide valores positivos por dez não cobre esses casos corretamente.
Prefira printf para exibir diretamente e snprintf para formatar strings com limite de tamanho. Escreva um formatador próprio somente quando precisar de uma representação específica que as conversões padrão não oferecem, e defina e verifique seu comportamento para toda a faixa de entradas. Para a notação científica comum, as conversões padrão são mais curtas e menos sujeitas a erros.