2009-05-06 10 views
4

Wie erstelle ich eine Zeichenkette, so dass sie Gleitkommazahlen so formatiert, dass sie keine Nachkommastellen oder Ziffern haben, wenn sie eine ganze Zahl ist, aber NICHT für größere Zahlen in wissenschaftliche Notation umschaltet?Zeichenkettenformat mit% g in C

Wenn ich tun:

float myFloat= 15.6f; 
float myInt = 5.0f; 
float myLarge = 7000000.0f; 
sprintf(out, "my float is %g", myFloat); 
sprintf(out, "my int is %g", myInt); 
sprintf(out, "my large is %g", myLarge); 

ich so etwas wie:

 
my float is 15.6 
my int is 5 
my large is 7e+07f 

ich alle einzelnen Format-String möchten, die 15,6, 5 geben wird, und 700000.

Edited Ursache Kommentare machen keine Formatierung:

das ist was ich dachte. aber ein Wrapper ist ziemlich unbequem obwohl, wie die Format-Strings in mehr Format-Strings eingebettet sind:

sprintf(buf, "%d %g", myInt, myFloat); 

wie, dass Sie wickeln?

sprintf(buf, "%d %g", myInt, Wrapper(myFloat));?? 

was sollte Wrapper zurück? Oder schlechter:

sprintf(buf, "%d %s", myInt, Wrapper(myFloat));?? 
+0

Wenn Sie% verwenden.* f, dann müssen Sie nur tun: sprintf (buf, "% d%. * f", myint, getPlaces (myFloat), myFloat); Kein Wrapper zum Generieren von Formatzeichenfolgen erforderlich. –

Antwort

5

Ich glaube nicht, dass Sie dies mit %g bekommen können, wie %g gibt Ihnen die kürzere %e oder %f.

Also, ich glaube nicht, dass es ein einziges printf Argument, das Sie erfüllt. Für 15.6 könnten Sie %2.1f verwenden; Für 7000000 könnten Sie %7.0f verwenden.

Ihre beste Wette ist wahrscheinlich, eine Wrapper-Funktion zu schreiben, die die Größe Ihres Wertes betrachten und das korrekte printf Argument anwenden würde.

+0

Ja, das ist, was ich dachte. das ist aber ziemlich unpraktisch, da die Formatzeichenfolgen in längere Formatzeichenfolgen eingebettet sind: > sprintf (buf, "% d% g", myInt, myFloat); Wie wickeln Sie das? > sprintf (buf, "% d% g", meinInt, Wrapper (myFloat)); ?? was sollte Wrapper zurückgeben? Oder schlechter: > sprintf (buf, "% d% s", meinInt, Wrapper (myFloat)); ?? –

+0

Hier ist ein Tja: Schreibe ein my_sprintf. Suchen Sie nach einem Token, das Sie definieren (etwas wie% y oder was auch immer), ersetzen Sie es und rufen Sie sprintf darunter mit der ersetzten Zeichenfolge auf. Auf diese Weise haben Sie my_sprintf (buf, "% d% y", myInt, myFloat); – joce

+0

Sie könnten Mike Kales Trick (%. * F) in Ihrem my_sprintf verwenden, anstatt eine tatsächliche Zeichenfolge zu übergeben. – joce

10

Sie können mit "%. * F" formatieren, die Ihnen ermöglicht, die Genauigkeit als einen separaten Parameter an z. sprintf. Ich habe das in der Vergangenheit verwendet, als ich 0, 1, 2, oder vielleicht 3 Ziffern schön ohne zusätzliche abschließende Nullen anzeigen wollte. Schreiben Sie eine kleine Hilfsfunktion, die das Double/Float übernimmt und eine ganzzahlige Genauigkeit zurückgibt (durch Multiplikation mit 1000 und dann mit Modulo 10, 100, 1000). Rufen Sie dann sprintf mit "%. * F" auf, rufen Sie die Hilfsfunktion auf und übergeben Sie den Float.

+0

+1 Das ist wirklich nett! Ich wusste nichts davon. – rampion

1

Mike's Ansatz ist vernünftig, aber Sie können die Anzahl der Ziffern direkt mit der log10-Funktion berechnen und entweder floor oder ceil verwenden, um zu überprüfen, ob Sie tatsächlich einen ganzzahligen Wert haben. Etwas wie:

#include <math.h> 
double x; 
... 
if (floor(x) == x && x != 0.0) { // x is an non-zero integer value 
    int digits = floor(log10(fabs(x)+0.5)) + 1; 
    printf("x is %.*f\n", digits, x); 
} 

Auspacken, dass die Kette von Funktionsaufrufen, nehmen wir zunächst den absoluten Wert um sicherzustellen, dass das Argument nicht negativ ist, fügen Sie 0,5 bis den bekannten ganzzahligen Wert Pflege von möglichen Rundungsfehlern bei der Berechnung nehmen log10 einer genauen Potenz von 10, kombiniere log10 und floor, um den Exponenten der größten Potenz von 10 weniger als fabs (x) +0.5 zu bekommen, und schließe schließlich 1, um die Anzahl der Stellen zu erhalten, die benötigt werden, um x darzustellen. Hier sind einige Beispielwerte (von Openoffice, aber die C log10 Funktion in ähnlicher Genauigkeit berechnen soll):

  x   log10(x+0.5) 
     1 0.176091259055681000 
     9 0.977723605288848000 
     10 1.021189299069940000 
     99 1.997823080745730000 
     100 2.002166061756510000 
     999 2.999782798454140000 
     1000 3.000217092972230000 
    10000 4.000021714181250000 
    100000 5.000002171466980000 
    1000000 6.000000217147190000 
    10000000 7.000000021714720000 
100000000 8.000000002171470000 
1000000000 9.000000000217150000 
+0

Ich denke, das OP will die Anzahl der Stellen nach dem Dezimalpunkt, nicht die Reihenfolge der Zahl. 1 + floor (log10 (1.234 + 0.5)) ist 1, nicht der (ich glaube) gewünscht 3. –

+0

Ja, ich vermisste, dass der Punkt von Mikes sukzessiven Mod-Operationen war, herauszufinden, wie viele Stellen nach dem Dezimalpunkt gedruckt werden Nicht ganzzahlige Werte. Ich konzentrierte mich auf den Teil von Seans Bitte, dass es keine nachstellbaren Ziffern oder Dezimalstellen für ganzzahlige Werte geben sollte. Sie können unsere beiden Ansätze kombinieren, um die Ziffern vor und nach dem Dezimalpunkt zu berechnen, um die erforderliche Gesamtpräzision zu berechnen. – dewtell

1

Ersetzen% g mit% .10g zu zeigen, bis zu 10 signifikanten Zahlen