HOWTO · C
Imprimir números en notación científica en C
Este artículo presenta cómo imprimir números en notación científica en C
En esta página
Usa la conversión %e o %E de printf para mostrar un valor de punto flotante en notación científica. La conversión en minúscula imprime el marcador del exponente en minúscula; la conversión en mayúscula lo imprime en mayúscula. Una precisión como %.3e establece cuántos dígitos aparecen después del punto decimal en la mantisa.
Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en 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;
}
Cómo funciona la notación científica en C
La notación científica expresa un valor distinto de cero como una mantisa multiplicada por una potencia de diez. La mantisa tiene un dígito distinto de cero antes del punto decimal; el exponente indica cuánto se desplaza el punto decimal. Por ejemplo, 123456 puede escribirse como 1.23456 × 10^5, mientras que 0.0000123 puede escribirse como 1.23 × 10^-5.
Esta notación cambia la forma en que se muestra un valor, pero no cómo lo almacena el tipo subyacente float o double. Los tipos de punto flotante binario tienen una precisión finita, por lo que muchas fracciones decimales se representan de forma aproximada en la memoria. Imprimir más dígitos puede revelar mejor esa aproximación almacenada, pero no aumenta la precisión del valor guardado.
Imprimir notación científica con printf
Las conversiones e y E dan formato a un argumento double en notación científica. El uso de mayúsculas en el marcador del exponente depende de la conversión: %e usa e y %E usa E. El exponente incluye un signo, y las implementaciones imprimen suficientes dígitos para representarlo. Usa %f si quieres comparar con la notación de punto fijo. La especificación POSIX de fprintf define las conversiones e y E, así como su comportamiento con respecto a la precisión.
En el ejemplo inicial, %.3e y %.3E muestran tres dígitos después del punto decimal en la mantisa. El signo del valor también aparece en el número formateado. Para valores cuyo tamaño hace difícil leer una salida de punto fijo, la notación científica mantiene compacta la mantisa y deja que el exponente indique la escala.
La conversión espera un argumento double. Al pasar un float a printf, este se convierte a double, pero un entero no. Para dar formato científico a un entero, conviértelo explícitamente; por ejemplo, usa (double)count junto con %e o %E. Los enteros grandes pueden perder dígitos de menor peso al convertirse si exceden la precisión que double puede representar.
Controlar la cantidad de dígitos después del punto decimal
Para %e y %E, la precisión cuenta los dígitos después del punto decimal, no el total de cifras significativas. Por tanto, %.2e imprime dos dígitos decimales en la mantisa, que suelen ser tres cifras significativas en total. Si omites la precisión, el valor predeterminado es seis dígitos después del punto decimal. El valor se redondea para mostrarlo con la precisión solicitada; el valor almacenado no cambia. La especificación POSIX de fprintf establece la regla de precisión y el valor predeterminado de seis dígitos.
Elige la precisión según el formato de visualización o intercambio que necesite tu aplicación. Imprimir más dígitos no garantiza que la cadena decimal represente exactamente el valor de punto flotante binario. Si necesitas una cantidad concreta de cifras significativas, ten en cuenta el dígito inicial de la mantisa al elegir la precisión.
Dar formato seguro a cadenas con notación científica
Cuando necesites guardar el número formateado o pasarlo a otra función, usa snprintf con una capacidad de búfer definida. Esa capacidad incluye el carácter nulo de terminación. La función devuelve la cantidad de caracteres que habría escrito, sin contar ese terminador; un valor de retorno mayor o igual que la capacidad indica que la salida se truncó. Un valor de retorno negativo indica un error de formato. La especificación POSIX de fprintf define el valor de retorno de snprintf y su comportamiento ante el truncamiento.
Ejecuta este ejemplo autónomo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en 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 escribe como máximo tantos caracteres como permita la capacidad disponible y termina el búfer con un carácter nulo cuando su capacidad es mayor que cero. Comprueba el valor de retorno antes de tratar el búfer como un resultado formateado completo. Evita usar sprintf sin límites cuando no tengas garantizado que el búfer será suficiente.
¿Conviene escribir una función personalizada para la notación científica?
Por lo general, no. %e y %E ya gestionan la mantisa, el exponente, el signo, el redondeo y el valor cero según las reglas de formato de la biblioteca de C. Una conversión escrita a mano debe tratar el cero por separado y normalizar tanto los valores menores que uno como los valores iguales o superiores a diez. También debe contemplar los valores negativos, el redondeo que cambia la mantisa y los límites del tipo numérico. Un bucle que solo divide valores positivos entre diez no cubre correctamente esos casos.
Usa printf para mostrar el resultado directamente y snprintf para crear cadenas con límites definidos. Escribe un formateador personalizado solo si necesitas una representación concreta que las conversiones estándar no ofrecen, y define y comprueba su comportamiento para todo el rango de entrada. Para la notación científica habitual, las conversiones estándar son más breves y menos propensas a errores.