Bienvenidos sean a este post, hoy veremos como formatear numeros con coma flotante.
En los dos posts anteriores estuvimos viendo como poder formatear la salida de un printf primero para enteros sin signos y en el siguiente post a los enteros con signos, pero que sucede cuando tenemos numeros de tipo float o double, es decir con decimales, bueno esos se manejan de una manera no tan distinta, para aplicarlo vamos a crear un nuevo archivo que llamaremos ejemplo31.c y le agregaremos este codigo inicial:
ejemplo31.c
#include <stdio.h>
int main()
{
double decimal = 987654321.987654321;
}
Al igual que vimos en los posts anteriores nuestra primera definicion sera sobre la variable que usaremos para trabajar, en este caso una de tipo double con bastantes decimales, nuestro sigueinte paso sera agregar el siguiente segmento de codigo:
printf("Usando los modificadores %%f, %%e y %%E:\n");
printf("Modif.\tValor Formateado\n");
printf("%%f\t[%f]\tpor defecto\n", decimal);
printf("%%.3f\t[%.3f]\t\t3 decimales\n", decimal);
printf("%%.8f\t[%.8f]\t8 decimales\n", decimal);
printf("%%.0f\t[%.0f]\t\tsin decimales\n", decimal);
printf("%%#.0f\t[%#.0f]\t\t0 decimales pero con punto decimal\n",
decimal);
printf("%%15.3f\t[%15.3f]\t3 decimales, ancho 15, alin. der\n",
decimal);
printf("%%-15.3f\t[%-15.3f]\t3 decimales, ancho 15, alin. izq\n",
decimal);
Aqui simplemente mostraremos las distintas formas basicas de formatear a nuestro numero con decimal, en las primeras dos lineas estan la etiquetas para identificarlas, despues comienza la magia, en la tercer linea simplemente lo mostraremos como se veria de forma predeterminada o por defecto indicando q es de tipo float (flotante), en la siguiente linea lo formatearemos para que muestre tres decimales despues de la coma o punto decimal en este caso, lo siguiente que hacemos sera lo mismo pero para que muestre ocho decimales, la siguiente ocultara todos los decimales, en la siguiente linea ocultara los decimales pero nos mostrara el punto, recuerden que es un lenguaje anglosajon y ellos tienen punto para los decimales y no coma como nosotros, en la siguiente establecemos un ancho de 15 numeros y con tres decimales despues del punto, como no informamos nada lo alineara por defecto a la derecha, en la siguiente linea hace exactamente lo mismo pero ahora le agregamos el simbolo para que lo alinee a la izquierda, un detalle que no comente es que para cada linea agregamos una descripcion de lo comentado anteriormente y recuerden que el \t equivale a hacer una tabulacion y lo usamos para darle un mejor formato, con esto comentado vamos a compilarlo y ver como es su salida:
tinchicus@dbn001vrt:~/lenguajes/C$ ./prog/ejemplo31
Usando los modificadores %f, %e y %E:
Modif. Valor Formateado
%f [987654321.987654] por defecto
%.3f [987654321.988] 3 decimales
%.8f [987654321.98765433] 8 decimales
%.0f [987654322] sin decimales
%#.0f [987654322.] 0 decimales pero con punto decimal
%15.3f [ 987654321.988] 3 decimales, ancho 15, alin. der
%-15.3f [987654321.988 ] 3 decimales, ancho 15, alin. izq
tinchicus@dbn001vrt:~/lenguajes/C$
Hasta aqui vimos como trabaja de una manera muy simple y con float, nuestro siguiente paso sera agregar el siguiente segmento de codigo:
printf("%%e\t[%e]\t\tusando anotacion exponencial\n", decimal);
printf("%%E\t[%E]\t\tusando anotacion EXPONENCIAL\n", decimal);
printf("%%.3e\t[%.3e]\t\texponente con 3 decimales\n", decimal);
printf("%%15.3e\t[%15.3e]\texponente con 3 decimales, ancho 15\n",
decimal);
printf("%%015.3e\t[%015.3e]\texpon. con 3 dec., ancho 15, compl-0\n",
decimal);
printf("%% 15.3e\t[% 15.3e]\texpon. con 3 dec., ancho 15", decimal);
printf(", espacio para signo\n");
printf("%%+15.3e\t[%+15.3e]\texpon. con 3 dec., ancho 15", decimal);
printf(", mostrar el signo\n");
printf("%%+015.3e[%+015.3e]\texpon. con 3 dec., ancho 15", decimal);
printf(", mostrar signo, completar con 0\n");
printf("%%.0e\t[%.0e]\t\t\texponente sin decimales\n", decimal);
printf("%%15.0e\t[%15.0e]\texponente sin decimales, ancho 15\n",
decimal);
Las dos primeras lineas seran para mostrar la anotacion exponencial en minuscula y mayuscula respectivamente pero de manera predeterminada, como cuando vimos la anotacion Hexadecimal, la siguiente linea es para reducir los decimales que mostraremos a tres, la siguiente es igual a la anterior pero le establecemos un ancho de quince numeros, a continuacion volvemos a hacer lo mismo pero le agregamos la opcon de que complete con ceros los elementos faltantes, la siguiente linea mostrara el exponente con tres decimales, el ancho de quince pero el espacio que dejamos es para dejar un espacio para el signo en caso de ser necesario, la siguiente linea hace lo mismo pero en lugar de dejar el espacio le pasamos el modificador para que nos muestre el signo, de nuevo en la siguiente linea vuelve a repetir lo mismo pero le agregamos el que complete con cero los elementos faltantes, en estas tres ultimas lineas si observan agregamos una linea posterior y esto es para terminar de completar la descripcion del modificador que estamos utilizando, es puramente estetico para la pagina pero sino lo agregan directamente a las comillas, la penultima linea nos mostrara el exponente pero sin decimales y la ultima linea hace lo mismo pero le pasamos un ancho de quince numeros, compilemos y veamos como es su salida:
...
%e [9.876543e+08] usando anotacion exponencial
%E [9.876543E+08] usando anotacion EXPONENCIAL
%.3e [9.877e+08] exponente con 3 decimales
%15.3e [ 9.877e+08] exponente con 3 decimales, ancho 15
%015.3e [0000009.877e+08] expon. con 3 dec., ancho 15, compl-0
% 15.3e [ 9.877e+08] expon. con 3 dec., ancho 15, espacio para signo
%+15.3e [ +9.877e+08] expon. con 3 dec., ancho 15, mostrar el signo
%+015.3e[+000009.877e+08] expon. con 3 dec., ancho 15, mostrar signo, completar con 0
%.0e [1e+09] exponente sin decimales
%15.0e [ 1e+09] exponente sin decimales, ancho 15
tinchicus@dbn001vrt:~/lenguajes/C$
Se tiene que repetir la salida anterior mas la salida de nuestro nuevo codigo, aqui podemos ver como se ajusta a nuestras necesidades, y como se ve afectado dependiendo de si establecemos mas o menos modificadores, con esto comentado vamos a agregar el siguiente segmento de codigo:
printf("%%a\t[%a]\tversion hexadecimal de double, exp=2^P\n", decimal);
printf("%%A\t[%A]\tversion HEXADECIMAL de double, exp=2^P\n", decimal);
Este es el modificador que nos permitira mostrar la version hexadecimal de un valor de tipo double o con coma flotante, al igual que vinimos viendo tenemos la opcion de mostrar todo en minuscula o mayuscula dependiendo de si el modificador esta en minuscula o mayuscula respectivamente, compilemos y veamos como es la nueva salida que se agrego:
...
%a [0x1.d6f3458fe6b75p+29] version hexadecimal de double, exp=2^P
%A [0X1.D6F3458FE6B75P+29] version HEXADECIMAL de double, exp=2^P
tinchicus@dbn001vrt:~/lenguajes/C$
Ahora solo nos resta ver como se puede establecer un ancho optimo para los valores de tipo double, para ello debemos agregar el siguiente bloque de codigo:
printf("\nUso de los modificadores %%g y %%G:\n");
printf("Modif.\t%%18.12g\t\t\t%%18.3g\t\t\t%%18.3G\t\t\t%%18g\n");
double k = decimal * 1e-15;
for(int i=0; i < 10; i++, k*=1000)
printf("\t[%18.12g]\t[%18.3g]\t[%18.3G]\t[%18g]\n",
k, k, k, k);
Este modificador tiene la particularidad de comportarse tanto como f como e, ambas versiones, dependiendo del valor que recibe, en las dos primeras lineas mostramos las etiquetas de como lo trabajaremos, para esta ocasion usaremos cuatro combinaciones distintas de modificadores, en el primero dejaremos doce decimales, en el segundo solamente tres, en el siguiente tres tambien pero con la opcion de mayusculas y el ultimo de manera predeterminada, en todos los casos establecemos un ancho de dieciocho, despues definimos una variable donde tomaremos a decimal para multiplicarlo por un numero muy chico para que nos quede un numero mas chico, por ultimo haremos un bucle donde pasaremos el valor de multiplicar el contenido de la variable anteriormente definida por 1000 en cada pasada, respetando el formato que pasamos en las etiquetas, con esto comentado compilemos y veamos como es su salida:
...
Uso de los modificadores %g y %G:
Modif. %18.12g %18.3g %18.3G %18g
[ 9.87654321988e-07] [ 9.88e-07] [ 9.88E-07] [ 9.87654e-07]
[ 0.000987654321988] [ 0.000988] [ 0.000988] [ 0.000987654]
[ 0.987654321988] [ 0.988] [ 0.988] [ 0.987654]
[ 987.654321988] [ 988] [ 988] [ 987.654]
[ 987654.321988] [ 9.88e+05] [ 9.88E+05] [ 987654]
[ 987654321.988] [ 9.88e+08] [ 9.88E+08] [ 9.87654e+08]
[ 987654321988] [ 9.88e+11] [ 9.88E+11] [ 9.87654e+11]
[ 9.87654321988e+14] [ 9.88e+14] [ 9.88E+14] [ 9.87654e+14]
[ 9.87654321988e+17] [ 9.88e+17] [ 9.88E+17] [ 9.87654e+17]
[ 9.87654321988e+20] [ 9.88e+20] [ 9.88E+20] [ 9.87654e+20]
tinchicus@dbn001vrt:~/lenguajes/C$
Pueden observar como de una manera mas simple y automatica nos permitio trabajar sin la necesidad de tener que verificar si es de un tipo u otro, y recuerden el valor siempre sera el mismo internamente lo unico que modificamos es la forma de representarlo, con esto cubrimos hasta ahora como trabajar con numeros pero en el proximo post pasaremos a las cadenas o string, pero antes de terminar veamos como es el codigo final de nuestro archivo:
ejemplo31.c
#include <stdio.h>
int main()
{
double decimal = 987654321.987654321;
printf("Usando los modificadores %%f, %%e y %%E:\n");
printf("Modif.\tValor Formateado\n");
printf("%%f\t[%f]\tpor defecto\n", decimal);
printf("%%.3f\t[%.3f]\t\t3 decimales\n", decimal);
printf("%%.8f\t[%.8f]\t8 decimales\n", decimal);
printf("%%.0f\t[%.0f]\t\tsin decimales\n", decimal);
printf("%%#.0f\t[%#.0f]\t\t0 decimales pero con punto decimal\n",
decimal);
printf("%%15.3f\t[%15.3f]\t3 decimales, ancho 15, alin. der\n",
decimal);
printf("%%-15.3f\t[%-15.3f]\t3 decimales, ancho 15, alin. izq\n",
decimal);
printf("%%e\t[%e]\t\tusando anotacion exponencial\n", decimal);
printf("%%E\t[%E]\t\tusando anotacion EXPONENCIAL\n", decimal);
printf("%%.3e\t[%.3e]\t\texponente con 3 decimales\n", decimal);
printf("%%15.3e\t[%15.3e]\texponente con 3 decimales, ancho 15\n",
decimal);
printf("%%015.3e\t[%015.3e]\texpon. con 3 dec., ancho 15, compl-0\n",
decimal);
printf("%% 15.3e\t[% 15.3e]\texpon. con 3 dec., ancho 15", decimal);
printf(", espacio para signo\n");
printf("%%+15.3e\t[%+15.3e]\texpon. con 3 dec., ancho 15", decimal);
printf(", mostrar el signo\n");
printf("%%+015.3e[%+015.3e]\texpon. con 3 dec., ancho 15", decimal);
printf(", mostrar signo, completar con 0\n");
printf("%%.0e\t[%.0e]\t\t\texponente sin decimales\n", decimal);
printf("%%15.0e\t[%15.0e]\texponente sin decimales, ancho 15\n",
decimal);
printf("%%a\t[%a]\tversion hexadecimal de double, exp=2^P\n", decimal);
printf("%%A\t[%A]\tversion HEXADECIMAL de double, exp=2^P\n", decimal);
printf("\nUso de los modificadores %%g y %%G:\n");
printf("Modif.\t%%18.12g\t\t\t%%18.3g\t\t\t%%18.3G\t\t\t%%18g\n");
double k = decimal * 1e-15;
for(int i=0; i < 10; i++, k*=1000)
printf("\t[%18.12g]\t[%18.3g]\t[%18.3G]\t[%18g]\n",
k, k, k, k);
}
Y este es la salida completa que deberian obtener:
tinchicus@dbn001vrt:~/lenguajes/C$ ./prog/ejemplo31
Usando los modificadores %f, %e y %E:
Modif. Valor Formateado
%f [987654321.987654] por defecto
%.3f [987654321.988] 3 decimales
%.8f [987654321.98765433] 8 decimales
%.0f [987654322] sin decimales
%#.0f [987654322.] 0 decimales pero con punto decimal
%15.3f [ 987654321.988] 3 decimales, ancho 15, alin. der
%-15.3f [987654321.988 ] 3 decimales, ancho 15, alin. izq
%e [9.876543e+08] usando anotacion exponencial
%E [9.876543E+08] usando anotacion EXPONENCIAL
%.3e [9.877e+08] exponente con 3 decimales
%15.3e [ 9.877e+08] exponente con 3 decimales, ancho 15
%015.3e [0000009.877e+08] expon. con 3 dec., ancho 15, compl-0
% 15.3e [ 9.877e+08] expon. con 3 dec., ancho 15, espacio para signo
%+15.3e [ +9.877e+08] expon. con 3 dec., ancho 15, mostrar el signo
%+015.3e[+000009.877e+08] expon. con 3 dec., ancho 15, mostrar signo, completar con 0
%.0e [1e+09] exponente sin decimales
%15.0e [ 1e+09] exponente sin decimales, ancho 15
%a [0x1.d6f3458fe6b75p+29] version hexadecimal de double, exp=2^P
%A [0X1.D6F3458FE6B75P+29] version HEXADECIMAL de double, exp=2^P
Uso de los modificadores %g y %G:
Modif. %18.12g %18.3g %18.3G %18g
[ 9.87654321988e-07] [ 9.88e-07] [ 9.88E-07] [ 9.87654e-07]
[ 0.000987654321988] [ 0.000988] [ 0.000988] [ 0.000987654]
[ 0.987654321988] [ 0.988] [ 0.988] [ 0.987654]
[ 987.654321988] [ 988] [ 988] [ 987.654]
[ 987654.321988] [ 9.88e+05] [ 9.88E+05] [ 987654]
[ 987654321.988] [ 9.88e+08] [ 9.88E+08] [ 9.87654e+08]
[ 987654321988] [ 9.88e+11] [ 9.88E+11] [ 9.87654e+11]
[ 9.87654321988e+14] [ 9.88e+14] [ 9.88E+14] [ 9.87654e+14]
[ 9.87654321988e+17] [ 9.88e+17] [ 9.88E+17] [ 9.87654e+17]
[ 9.87654321988e+20] [ 9.88e+20] [ 9.88E+20] [ 9.87654e+20]
tinchicus@dbn001vrt:~/lenguajes/C$
En resumen, hoy hemos visto como formatear mediante printf valores con decimales, sus variables mas simples con la opcion de f, su opcion un poco mas compleja mediante la e, despues como convertirlos en hexadecimal mediante la a, para finalmente ver como es por medio de g, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
