significativas reglas redondeo quimica operaciones las importancia ejercicios ejemplos con cifras c format alignment printf specifier

reglas - Tratando 0 como una cifra significativa en printf% g formato especificador



importancia de las cifras significativas (2)

Estoy tratando de imprimir los números de coma flotante 1.2345678, 0.1234567, 123.45678 usando printf de tal manera que solo se impriman los primeros n caracteres. Quiero que este número se alinee. El especificador de formato% g en printf ("% * g", n, var) hace esto pero el especificador no trata el 0 en 0.1234567 como una cifra significativa. Esto hace que la alineación de 0.1234567 se apague con las otras dos figuras.

¿Cuál es la mejor manera de alinear los números en los formatos dados? ¿O tratando 0 como significativo con% g o usando algún otro método?


Un método de fuerza bruta intenta varias precisiones de %.*g hasta el éxito.

El principal obstáculo para calcular el ancho de la impresión antes de llamar a printf() es que existen casos de esquina como 0.9995. Los efectos sutiles del redondeo hacen que sea más simple llamar a sprintf() un momento posterior. Se podría usar un código adicional para hacer una mejor conjetura inicial en lugar de comenzar en prec = n - 1

int g_print(double x, int n) { int width; char buffer[n + 1]; for (int prec = n - 1; prec >= 0; prec--) { width = snprintf(buffer, sizeof buffer, "%.*g", prec, x); // printf(" n:%2d p:%2d w:%2d <%s>/n", n, prec, width, buffer); if (width > 0 && (unsigned) width < sizeof buffer) { return printf("%2d <%s>/n", n, buffer); } } // Try with %f width = snprintf(buffer, sizeof buffer, "%.0f", x); if (width > 0 && (unsigned) width < sizeof buffer) { return printf("%2d <%s>/n", n, buffer); } printf("%2d Fail %e/n", n, x); return 0; // fail } void g_print_test(double x) { // Need at least width 7 for all values for (int n = 8; n >= 1; n--) { if (g_print(x, n) == 0) break; } } int main() { g_print_test(1.2345678); g_print_test(0.1234567); g_print_test(123.45678); g_print_test(DBL_MAX); g_print_test(-DBL_MAX); g_print_test(-DBL_MIN); return 0; }

Salida

n text... 8 <1.234568> 7 <1.23457> 6 <1.2346> 5 <1.235> 4 <1.23> 3 <1.2> 2 <1> 1 <1> 8 <0.123457> 7 <0.12346> 6 <0.1235> 5 <0.123> 4 <0.12> 3 <0.1> 2 <0> 1 <0> 8 <123.4568> 7 <123.457> 6 <123.46> 5 <123.5> 4 <123> 3 <123> 2 Fail 1.234568e+02 8 <1.8e+308> 7 <2e+308> 6 <2e+308> 5 Fail 1.797693e+308 8 <-2e+308> 7 <-2e+308> 6 Fail -1.797693e+308 8 <-2e-308> 7 <-2e-308> 6 <-0> 5 <-0> 4 <-0> 3 <-0> 2 <-0> 1 Fail -2.225074e-308


Por definición, los ceros a la izquierda no son cifras significativas. Si desea que se impriman los primeros N dígitos, incluidos los ceros iniciales, convierta primero los números en cadenas y use printf("%.*s", n, var_as_string) .

De esta manera, los primeros n caracteres se imprimen, como usted pidió. Por supuesto, la marca decimal . , como cualquier otro personaje, ahora es significativo, contrario a %g .