Pregunta

El problema es asignar estáticamente un buffer lo suficientemente grande como para adaptarse a una doble impreso, formateado con% g en la máxima precisión. Esto parece una tarea bastante sencilla, bu tengo problemas. El mejor que he llegado con (suponiendo que el número que se va a imprimir se x) es

char buf[1 + DBL_DIG + DBL_DIG + 1 + 1 + 1 + DBL_DIG + 1];
int len = sprintf(buf, "%.*g", DBL_DIG, x);

La macro DBL_DIG es de float.h, y al parecer se supone que indica la máxima precisión para el tipo doble. Necesitamos:

  • 1 byte para un signo negativo
  • suficientes bytes para capturar los dígitos significativos
  • a lo más un char separador '(coma, etc.) por dígito
  • 1 byte para un punto decimal
  • 1 byte para 'e'
  • 1 byte para la señal en el exponente
  • algunos bytes para el exponente
  • 1 byte para los últimos nula escrito por sprintf.

Estoy usando el número de dígitos significativos como un límite superior en el número de dígitos en el exponente. ¿He cometido errores? ¿Hay una solución mejor? ¿Debo asignar 64, 128, o 256 bytes y esperar lo mejor?

¿Fue útil?

Solución 4

En lugar de utilizar sprintf, podría utilizar asprintf . Esta reserva un buffer de tamaño correcto para adaptarse a su cadena.

Otros consejos

No se puede calcular previamente el tamaño en tiempo de compilación. El% g formateador toma la configuración regional en cuenta (por del 1000 separador etc.) Ver http://linux.die.net/man/3/sprintf para una Descripción de la forma de calcular el tamaño de forma segura.

Uso snprintf() para averiguar el número de caracteres que necesita:

#include <float.h> /* DBL_DIG */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
  double x = rand() / (double)RAND_MAX;
  char find_len[1];
  int need_len;
  char *buf;

  need_len = snprintf(find_len, 1, "%.*g", DBL_DIG, x);
  buf = malloc(need_len + 1);
  if (buf) {
    int used = sprintf(buf, "%.*g", DBL_DIG, x);
    printf("need: %d; buf:[%s]; used:%d\n", need_len, buf, used);
    free(buf);
  }
  return 0;
}

Es necesario un compilador C99 de snprintf().
snprintf() fue definida por el estándar C99. Una aplicación C89 no está obligado a tener snprintf() definido, y si se tiene como una extensión, no se requiere que el "trabajo" como se describe en la norma C99.

Dos cosas:% g no muestra todos los dígitos representables,% g muestra un buen resultado para la seres humanos redondeado. Puede especificar la precisión utilizando% f% o correo si desea un resultado diferente.

No utilice nunca sprintf () en lugar de utilizar snprintf (). En tu caso: int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

  

¿Debo redondear hasta 64, 128, o   256 y esperar lo mejor?

Sí, sólo hacer eso -.-

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top