Ein 64-Bit-Double kann eine ganze Zahl +/- 2 53 genau darstellen
Angesichts dieser Tatsache verwende ich für alle meine Typen einen Doppeltyp als Einzeltyp, da meine größte Ganzzahl vorzeichenloses 32-Bit ist.
Aber jetzt muss ich diese Pseudo-Ganzzahlen drucken, aber das Problem ist, dass sie auch mit tatsächlichen Doppelwerten gemischt werden.
Wie drucke ich diese Doppelbilder gut in Java?
Ich habe versucht String.format("%f", value)
, was nah ist, außer dass ich viele nachgestellte Nullen für kleine Werte bekomme.
Hier ist eine Beispielausgabe von %f
232.00000000 0,18000000000 1237875192.0 4.5800000000 0,00000000 1.23450000
Was ich will ist:
232 0,18 1237875192 4.58 0 1,2345
Sicher, ich kann eine Funktion schreiben, um diese Nullen zu trimmen, aber das ist ein großer Leistungsverlust aufgrund von String-Manipulationen. Kann ich es mit einem anderen Formatcode besser machen?
BEARBEITEN
Die Antworten von Tom E. und Jeremy S. sind nicht akzeptabel, da beide willkürlich auf 2 Dezimalstellen gerundet werden. Bitte verstehen Sie das Problem, bevor Sie antworten.
BEARBEITEN 2
Bitte beachten Sie, dass String.format(format, args...)
ist locale-abhängig (siehe Antworten unten).
System.out.println("YOUR STRING" + YOUR_DOUBLE_VARIABLE);
Antworten:
Wenn die Idee darin besteht, Ganzzahlen zu drucken, die als Doppelte gespeichert sind, als wären sie Ganzzahlen, und ansonsten die Doppelten mit der minimal erforderlichen Genauigkeit zu drucken:
Produziert:
Und ist nicht auf String-Manipulation angewiesen.
quelle
double
größer als der Maximalwertint
ist. Auchlong
damit würde es bei großen Zahlen noch scheitern. Außerdem wird ein String in Exponentialform, z. B. "1.0E10", für große Werte zurückgegeben, was der Fragesteller wahrscheinlich nicht wünscht. Verwenden Sie%f
anstelle der%s
Zeichenfolge im zweiten Format, um dies zu beheben.%f
. Die Antwort ist spezifisch für die beschriebene Situation und die gewünschte Ausgabe. Das OP schlug vor, dass ihr Maximalwert ein 32-Bit-Int ohne Vorzeichen war, wasint
akzeptabel war (vorzeichenlos, in Java nicht vorhanden, und kein Exemplar war problematisch), aber das Wechselnint
zulong
ist eine triviale Lösung, wenn die Situation anders ist.String.format("%s",d)
??? Sprechen Sie über unnötigen Overhead. Verwenden SieDouble.toString(d)
. Gleiches gilt für die anderen :Long.toString((long)d)
.%s
es mit Locales nicht funktioniert. Auf Deutsch verwenden wir ein "," anstelle eines "." in Dezimalzahlen. WährendString.format(Locale.GERMAN, "%f", 1.5)
"1.500000" zurückgegeben wird, wirdString.format(Locale.GERMAN, "%s", 1.5)
"1.5" zurückgegeben - mit einem ".", Was in deutscher Sprache falsch ist. Gibt es auch eine vom Gebietsschema abhängige Version von "% s"?Wie in den Kommentaren erwähnt, ist dies nicht die richtige Antwort auf die ursprüngliche Frage.
Das heißt, es ist eine sehr nützliche Möglichkeit, Zahlen ohne unnötige nachgestellte Nullen zu formatieren.
quelle
quelle
Zusamenfassend:
Wenn Sie nachgestellte Nullen und Gebietsschemaprobleme beseitigen möchten, sollten Sie Folgendes verwenden:
Erläuterung:
Warum andere Antworten nicht zu mir passten:
Double.toString()
oderSystem.out.println
oderFloatingDecimal.toJavaFormatString
verwendet wissenschaftliche Notationen, wenn double kleiner als 10 ^ -3 oder größer oder gleich 10 ^ 7 istBei Verwendung
%f
beträgt die Standard-Dezimalgenauigkeit 6, andernfalls können Sie sie fest codieren. Wenn Sie jedoch weniger Dezimalstellen haben, werden zusätzliche Nullen hinzugefügt. Beispiel:indem Sie eine Dezimalgenauigkeit verwenden
setMaximumFractionDigits(0);
oder%.0f
entfernen, die für Ganzzahlen / Longs, aber nicht für Double in Ordnung istMit DecimalFormat sind Sie lokal abhängig. Im französischen Gebietsschema ist das Dezimaltrennzeichen ein Komma, kein Punkt:
Durch die Verwendung des Gebietsschemas ENGLISH wird sichergestellt, dass Sie überall dort, wo Ihr Programm ausgeführt wird, einen Punkt für das Dezimaltrennzeichen erhalten
Warum dann 340 für
setMaximumFractionDigits
?Zwei Gründe :
setMaximumFractionDigits
akzeptiert eine Ganzzahl, aber für die Implementierung sind maximal Ziffern zulässig, vonDecimalFormat.DOUBLE_FRACTION_DIGITS
denen 340 entsprichtDouble.MIN_VALUE = 4.9E-324
Mit 340 Stellen können Sie also Ihre doppelte und lockere Präzision nicht abrundenquelle
0
#.
DecimalFormat.DOUBLE_FRACTION_DIGITS
sondern den Wert 340, für den Sie einen Kommentar abgeben, um zu zeigen, dass er gleich istDecimalFormat.DOUBLE_FRACTION_DIGITS
. Warum nicht einfach die Konstante benutzen ???Warum nicht:
Dies sollte mit den von Double unterstützten Extremwerten funktionieren. Ausbeuten:
quelle
"%s"
Grundsätzlich Anrufe,d.toString()
aber es funktioniert nicht mitint
oder wennd==null
!Auf meinem Computer ist die folgende Funktion ungefähr siebenmal schneller als die von JasonDs Antwort bereitgestellte Funktion , da sie Folgendes vermeidet
String.format
:quelle
Meine 2 Cent:
quelle
return String.format(Locale.US, (n % 1 == 0 ? "%.0f" : "%.1f"), n);
.Nein, egal.
Der Leistungsverlust aufgrund von String-Manipulationen ist Null.
Und hier ist der Code, um das Ende danach zu kürzen
%f
quelle
Verwenden Sie ein
DecimalFormat
undsetMinimumFractionDigits(0)
quelle
setMaximumFractionDigits(2)
undsetGroupingUsed(false)
(OPs erwähnen es nicht, aber aus dem Beispiel scheint es, dass es erforderlich ist). Auch ein kleiner Testfall tut nicht weh, da er in diesem Fall trivial ist. Trotzdem, da ich denke, dass es die einfachste Lösung ist, ist ein Upvote ein Upvote :)quelle
Bitte beachten Sie, dass
String.format(format, args...)
ist locale-abhängig , da es formatiert das Standardgebietsschema des Benutzers verwenden, die wahrscheinlich mit Komma und sogar Räumen im Innern wie ist 123 456789 oder 123,456.789 , die nicht genau sein kann , was Sie erwarten.Sie können es vorziehen, zu verwenden
String.format((Locale)null, format, args...)
.Zum Beispiel,
druckt
und das ist was wird
String.format(format, args...)
in verschiedenen Ländern geschehen.EDIT Ok, da es eine Diskussion über Formalitäten gegeben hat:
quelle
Ich habe eine
DoubleFormatter
große Anzahl von Doppelwerten effizient in einen schönen / präsentablen String konvertiert:Hier der Code:
Hinweis: Ich habe 2 Funktionen aus der GUAVA-Bibliothek verwendet. Wenn Sie GUAVA nicht verwenden, codieren Sie es selbst:
quelle
Dieser wird die Arbeit gut erledigen, ich weiß, dass das Thema alt ist, aber ich hatte mit dem gleichen Problem zu kämpfen, bis ich dazu kam. Ich hoffe, jemand findet es nützlich.
quelle
quelle
quelle
Späte Antwort aber ...
Sie sagten , Sie wählen Sie Ihre Zahlen mit dem speichern Doppel Typ . Ich denke, dies könnte die Wurzel des Problems sein, da Sie dadurch gezwungen werden, Ganzzahlen in Doppelwerten zu speichern (und daher die anfänglichen Informationen über die Art des Werts zu verlieren). Wie wäre es, wenn Sie Ihre Zahlen in Instanzen der Number- Klasse (Superklasse von Double und Integer) speichern und sich auf Polymorphismus verlassen, um das richtige Format für jede Zahl zu bestimmen?
Ich weiß, dass es aus diesem Grund möglicherweise nicht akzeptabel ist, einen ganzen Teil Ihres Codes umzugestalten, aber es könnte die gewünschte Ausgabe ohne zusätzlichen Code / Casting / Parsing erzeugen.
Beispiel:
Erzeugt die folgende Ausgabe:
quelle
Das habe ich mir ausgedacht:
Einfacher Einzeiler, wird nur bei Bedarf in int umgewandelt
quelle
Formatieren Sie den Preis mit Gruppierung, Rundung, ohne unnötige Nullen (doppelt).
Regeln:
2.0000 = 2; 1.0100000 = 1.01
)2.010 = 2.01; 0.20 = 0.2
)1.994 = 1.99; 1.995 = 2; 1.006 = 1.01; 0.0006 -> 0
)0
(null/-0 = 0
)$
(= $56/-$56
)101101.02 = $101,101.02
)Mehr Beispiele:
Geschrieben in Kotlin als lustige Erweiterung von Double (Ursache in Android), kann aber leicht in Java konvertiert werden, da Java-Klassen verwendet wurden.
Wie benutzt man:
Informationen zu DecimalFormat : https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
quelle
Ich musste diese Ursache nutzen
d == (long)d
, um mich im Sonarbericht zu verletzenquelle
Dies ist das Ergebnis einiger Tests:
quelle
Hier sind zwei Möglichkeiten, um dies zu erreichen. Erstens der kürzere (und wahrscheinlich bessere) Weg:
Und hier ist der längere und wahrscheinlich schlechtere Weg:
quelle
Für Kotlin können Sie folgende Erweiterungen verwenden:
quelle
Hier ist eine weitere Antwort, bei der NUR eine Dezimalstelle angehängt werden kann, wenn die Dezimalstelle nicht Null war.
quelle
Hier ist eine Antwort, die tatsächlich funktioniert (Kombination verschiedener Antworten hier)
quelle
Ich weiß, dass dies ein wirklich alter Thread ist. Aber ich denke, der beste Weg, dies zu tun, ist wie folgt:
Ausgabe:
Das einzige Problem ist das letzte, bei dem .0 nicht entfernt wird. Aber wenn Sie damit leben können, funktioniert dies am besten. % .2f rundet es auf die letzten 2 Dezimalstellen. DecimalFormat auch. Wenn Sie alle Dezimalstellen benötigen, aber nicht die nachgestellten Nullen, funktioniert dies am besten.
quelle
System.out.println(new java.text.DecimalFormat("#.##").format(1.0005));
wird gedruckt1
Dadurch lässt der String die Tailing-0-s fallen.
quelle