Ich stolpere immer wieder über die Formatspezifizierer für die printf () - Funktionsfamilie. Ich möchte in der Lage sein, ein Double (oder Float) mit einer maximal angegebenen Anzahl von Stellen nach dem Dezimalpunkt zu drucken. Wenn ich benutze:
printf("%1.3f", 359.01335);
printf("%1.3f", 359.00999);
Ich bekomme
359.013
359.010
Anstelle des gewünschten
359.013
359.01
Kann mir jemand helfen?
Antworten:
Dies ist mit den normalen
printf
Formatspezifizierern nicht möglich. Das nächste, was Sie bekommen könnten, wäre:aber die ".6" ist also die gesamte numerische Breite
bricht es.
Was Sie können tun , ist auf
sprintf("%.20g")
die Zahl in einen String - Puffer dann die Zeichenfolge manipulieren , um nur haben N Zeichen hinter dem Komma.Angenommen, Ihre Zahl befindet sich in der Variablen num, entfernt die folgende Funktion alle bis auf die ersten
N
Dezimalstellen und entfernt dann die nachfolgenden Nullen (und den Dezimalpunkt, wenn sie alle Nullen waren).Wenn Sie nicht zufrieden mit dem Abschneiden Aspekte sind (was machen würde
0.12399
in0.123
sie eher als Rundung0.124
), können Sie tatsächlich die Rundung Einrichtungen bereits zur Verfügung gestellt nutzenprintf
. Sie müssen nur die Zahl vorher analysieren, um die Breiten dynamisch zu erstellen, und diese dann verwenden, um die Zahl in eine Zeichenfolge umzuwandeln:In
nDecimals()
diesem Fall geht es darum, die Feldbreiten korrekt zu berechnen und die Zahl dann mit einer darauf basierenden Formatzeichenfolge zu formatieren. Das Testkabelmain()
zeigt dies in Aktion:Sobald Sie den korrekt gerundeten Wert haben, können Sie diesen erneut übergeben,
morphNumericString()
um nachfolgende Nullen zu entfernen, indem Sie einfach Folgendes ändern:in:
(oder
morphNumericString
am Ende aufrufen,nDecimals
aber in diesem Fall würde ich die beiden wahrscheinlich nur zu einer Funktion kombinieren), und am Ende erhalten Sie:quelle
.
ausgegangen wird, dass die Dezimalstelle lautet. In einigen Regionen ist die Dezimalstelle tatsächlich ein,
Komma.atof
der gleiche Wert zurückgegeben wird.0.10000000000000000555
sein wird ,0.1
wenn abgestreift zurück. Das Problem kann auftreten, wenn Sie einen Wert haben, der leicht darunter liegt, z. B. wenn die nächstgelegene Darstellung von42.1
war42.099999999314159
. Wenn Sie damit wirklich umgehen wollten, müssten Sie wahrscheinlich auf der Grundlage der zuletzt entfernten Ziffer runden, anstatt abzuschneiden.printf
ähnliche Funktionen zu erstellen, da diese bereits dynamische Parameter (*
Sonderzeichen) unterstützen: Beispielsweise wirdprintf("%*.*f", total, decimals, x);
eine Zahl mit der dynamisch angegebenen Gesamtfeldlänge und den Dezimalstellen ausgegeben.Um die nachgestellten Nullen zu entfernen, sollten Sie das Format "% g" verwenden:
Nachdem die Frage ein wenig geklärt war, wurde nicht nur die Unterdrückung von Nullen gestellt, sondern auch die Ausgabe auf drei Dezimalstellen begrenzt. Ich denke, das geht nicht nur mit Sprintf-Format-Strings. Wie Pax Diablo betonte, wäre eine Manipulation der Saiten erforderlich.
quelle
Ich mag die Antwort von R. leicht optimiert:
'1000' bestimmt die Genauigkeit.
Leistung auf die Rundung von 0,5.
BEARBEITEN
Ok, diese Antwort wurde einige Male bearbeitet und ich verlor den Überblick, was ich vor ein paar Jahren dachte (und ursprünglich erfüllte sie nicht alle Kriterien). Hier ist also eine neue Version (die alle Kriterien erfüllt und negative Zahlen korrekt behandelt):
Und die Testfälle:
Und die Ausgabe der Tests:
Jetzt sind alle Kriterien erfüllt:
Leider ist diese Antwort zweizeilig, da
sprintf
die Zeichenfolge nicht zurückgegeben wird.quelle
Ich suche die Zeichenfolge (beginnend ganz rechts) für das erste Zeichen im Bereich
1
bis9
(ASCII - Wert49
-57
) dannnull
(auf0
) jedes Zeichen rechts davon - siehe unten:quelle
Was ist mit so etwas (kann Rundungsfehler und Probleme mit negativen Werten haben, die debuggt werden müssen und als Übung für den Leser verbleiben):
Es ist leicht programmatisch, aber es bringt Sie zumindest nicht dazu, Saiten zu manipulieren.
quelle
Eine einfache Lösung, die jedoch die Arbeit erledigt, eine bekannte Länge und Präzision zuweist und die Möglichkeit vermeidet, ein exponentielles Format zu verwenden (was ein Risiko darstellt, wenn Sie% g verwenden):
Fügen Sie "elses" hinzu oder entfernen Sie sie, wenn Sie maximal 2 Dezimalstellen möchten. 4 Dezimalstellen; etc.
Zum Beispiel, wenn Sie 2 Dezimalstellen wollten:
Wenn Sie die Mindestbreite angeben möchten, um die Felder ausgerichtet zu halten, erhöhen Sie sie nach Bedarf, z. B.:
Sie können dies auch in eine Funktion konvertieren, bei der Sie die gewünschte Feldbreite übergeben:
quelle
d = 0.0001
: dannfloor(d)
ist0
, also ist der Unterschied größer als 0,000001,DoubleEquals
ist also falsch, so dass der Bezeichner nicht verwendet wird"%.0f"
: Sie sehen nachgestellte Nullen von"%*.2f"
oder"%*.3f"
. Es beantwortet also nicht die Frage.Ich habe Probleme in einigen der veröffentlichten Lösungen gefunden. Ich habe dies basierend auf den obigen Antworten zusammengestellt. Es scheint für mich zu funktionieren.
quelle
Einige der hoch bewerteten Lösungen schlagen den
%g
Konvertierungsspezifizierer von vorprintf
. Dies ist falsch, weil es Fälle gibt, in denen%g
wissenschaftliche Notation erzeugt wird. Andere Lösungen verwenden Mathematik, um die gewünschte Anzahl von Dezimalstellen zu drucken.Ich denke, die einfachste Lösung besteht darin,
sprintf
mit dem%f
Konvertierungsspezifizierer zu arbeiten und nachgestellte Nullen und möglicherweise einen Dezimalpunkt manuell aus dem Ergebnis zu entfernen. Hier ist eine C99-Lösung:Beachten Sie, dass die für Ziffern und das Dezimaltrennzeichen verwendeten Zeichen vom aktuellen Gebietsschema abhängen. Der obige Code setzt ein Gebietsschema in C oder US-Englisch voraus.
quelle
Hier ist mein erster Versuch einer Antwort:
Bekannte Fehler: Möglicher Pufferüberlauf je nach Format. Wenn "." ist aus einem anderen Grund vorhanden als% f, kann ein falsches Ergebnis auftreten.
quelle
Warum nicht einfach so machen?
quelle
Leichte Abweichung von oben:
Code hier:
Es besteht immer noch die Möglichkeit eines Überlaufs. Seien Sie also vorsichtig
quelle
Ich würde sagen, Sie sollten verwenden
printf("%.8g",value);
Wenn Sie verwenden, erhalten
"%.6g"
Sie für einige Zahlen wie 32.230210 nicht die gewünschte Ausgabe. Es sollte gedruckt werden,32.23021
aber es wird gedruckt32.2302
quelle
Ihr Code rundet aufgrund der ".3" vor dem f auf drei Dezimalstellen
Wenn Sie also die zweite Zeile auf zwei Dezimalstellen gerundet haben, sollten Sie sie folgendermaßen ändern:
Dieser Code gibt Ihre gewünschten Ergebnisse aus:
* Beachten Sie, dass dies davon ausgeht, dass Sie es bereits in separaten Zeilen drucken lassen. Wenn dies nicht der Fall ist, wird es durch Folgendes verhindert, dass es in derselben Zeile gedruckt wird:
Der folgende Programmquellcode war mein Test für diese Antwort
quelle