Frage

Das Problem ist statisch einen Puffer groß genug, um eine gedruckte zuzuteilen Doppel zu passen, wobei% g bei maximaler Genauigkeit formatiert. Dies scheint eine einfache genug Aufgabe, bu Ich habe Probleme. Das Beste, was ich gekommen sind, sich mit (vorausgesetzt, die Anzahl gedruckt werden soll, x)

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

Das DBL_DIG Makro ist aus float.h, und anscheinend ist es angeblich die doppelte maximale Präzision für den Typ anzuzeigen. Wir brauchen:

  • 1 Byte für ein negatives Vorzeichen
  • genug Bytes, die die signifikanten Stellen zu erfassen
  • höchstens ein 'Separator' char (Komma, etc.) pro Ziffer
  • 1 Byte für ein Dezimalzeichen
  • 1 Byte für 'e'
  • 1 Byte für die Zeichen auf dem Exponenten
  • einige Bytes für die Exponenten
  • 1 Byte für die von sprintf null geschrieben Rückstand.

Ich bin mit der Anzahl der signifikanten Stellen als Obergrenze für die Anzahl der Stellen im Exponenten. Habe ich irgendwelche Fehler gemacht? Gibt es eine bessere Lösung? Soll ich nur 64 zuteilen, 128 oder 256 Bytes und das Beste hoffen?

War es hilfreich?

Lösung 4

Anstelle der Verwendung von sprintf, könnte man a href = "http://www.freebsd.org/cgi/man.cgi?query=asprintf&apropos=0&sektion=0&manpath=FreeBSD+7.2-RELEASE&format=html" verwenden asprintf . Dies reserviert einen Puffer mit der richtigen Größe der Zeichenfolge zu passen.

Andere Tipps

Sie können nicht im Voraus berechnen die Größe bei der Kompilierung. Der% g Formatierer nimmt den locale berücksichtigt (für den Separator usw., 1000) Siehe http://linux.die.net/man/3/sprintf für eine Beschreibung, wie die Größe sicher zu berechnen.

Verwenden snprintf(), um herauszufinden, wie viele Zeichen, die Sie brauchen:

#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;
}

Sie benötigen einen C99-Compiler für snprintf().
snprintf() wurde von dem C99-Standard definiert. Eine C89-Implementierung nicht haben snprintf() definiert, erforderlich und wenn es als eine Erweiterung hat, ist es nicht zu „arbeiten“ erforderlich, wie durch den C99-Standard beschrieben.

Zwei Dinge:% g zeigt nicht alle der darstellbaren Ziffern% g zeigt eine schöne-für-Menschen Ergebnis abgerundet. Sie können die Präzision mit% f oder% e angeben, wenn Sie ein anderes Ergebnis möchten.

Verwenden Sie niemals sprintf () statt snprintf () verwenden. In deinem Fall: int len = snprintf(buf, dimensionof(buf), "%.*f", DBL_DIG, x);

  

Soll ich abzurunden nur zu 64 bis 128, oder   und 256 auf das Beste hoffen?

Ja, genau das tun -.-

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top