Was ich möchte, ist eine Methode, um ein Double in eine Zeichenfolge umzuwandeln, die mit der Half-Up-Methode rundet. Wenn also die zu rundende Dezimalstelle 5 ist, wird immer auf die nächste Zahl gerundet. Dies ist die Standardmethode zum Runden, die die meisten Menschen in den meisten Situationen erwarten.
Ich möchte auch, dass nur signifikante Ziffern angezeigt werden - dh es sollten keine nachgestellten Nullen vorhanden sein.
Ich weiß, dass eine Methode, dies zu tun, darin besteht, die String.format
Methode zu verwenden:
String.format("%.5g%n", 0.912385);
kehrt zurück:
0.91239
Das ist großartig, zeigt jedoch immer Zahlen mit 5 Dezimalstellen an, auch wenn sie nicht signifikant sind:
String.format("%.5g%n", 0.912300);
kehrt zurück:
0.91230
Eine andere Methode ist die Verwendung von DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
kehrt zurück:
0.91238
Wie Sie jedoch sehen können, wird eine halbgleichmäßige Rundung verwendet. Das heißt, es wird abgerundet, wenn die vorherige Ziffer gerade ist. Was ich möchte, ist Folgendes:
0.912385 -> 0.91239
0.912300 -> 0.9123
Was ist der beste Weg, um dies in Java zu erreichen?
"#.##"
, RundungHALF_UP
.256.335f
->"256.33"
... (Beispiel stammt aus Kommentaren zur Antwort von @ asterite).Unter der Annahme ,
value
eindouble
, können Sie tun:Das entspricht einer Genauigkeit von 5 Stellen. Die Anzahl der Nullen gibt die Anzahl der Dezimalstellen an.
quelle
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.265.335
bedeutet wirklich265.335 += tolerance
, wo die Toleranz von früheren Operationen und dem Bereich der Eingabewerte abhängt. Wir kennen den wahren, genauen Wert nicht. Bei den Kantenwerten ist jede Antwort wohl richtig. Wenn wir genau sein müssen, sollten wir nicht doppelt arbeiten. Dasfail
hier ist nicht in der Umstellung auf Double. Es ist im OP-Denken, dass er sich darauf verlassen kann265.335
, dass der Eingang genau das ist.bekommst du ein
BigDecimal
. Um die Zeichenfolge aus ihm heraus, rufen Sie einfach , dassBigDecimal
‚stoString
Methode oder dastoPlainString
Verfahren für Java 5+ für ein einfaches Format - String.Beispielprogramm:
quelle
new BigDecimal(doubleVar)
Sie sie, da dies zu Problemen mit der Rundung von Gleitkommazahlen führen kanndouble val = 265.335;
,BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.34
, aber(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.33
.Sie können auch die verwenden
um sicherzustellen, dass Sie die nachgestellten Nullen haben.
quelle
RoundingMode.
Decimal mode
verwendet standardmäßigRoundingMode.HALF_EVEN.
Wie einige andere angemerkt haben, ist die richtige Antwort, entweder
DecimalFormat
oder zu verwendenBigDecimal
. Floating-Point nicht hat Dezimalstellen so dass Sie nicht möglicherweise Aufrunden / Abrunden auf eine bestimmte Anzahl von ihnen an erster Stelle. Sie müssen in einem Dezimalradix arbeiten, und genau das tun diese beiden Klassen.Ich poste den folgenden Code als Gegenbeispiel zu allen Antworten in diesem Thread und in der Tat überall in StackOverflow (und anderswo), die eine Multiplikation gefolgt von einer Kürzung gefolgt von einer Division empfehlen. Befürworter dieser Technik müssen erklären, warum der folgende Code in über 92% der Fälle die falsche Ausgabe erzeugt.
Ausgabe dieses Programms:
BEARBEITEN: Um einige Kommentare unten anzusprechen, habe ich den Modulteil der Testschleife mit
BigDecimal
undnew MathContext(16)
für die Moduloperation wie folgt überarbeitet :Ergebnis:
quelle
100 trials 94 errors
Sie sollten mit einem Test beginnen, der erfolgreich ist, und zeigen, dass das Einführen von Rundungen den Test unterbricht .double
als keine Fehler ideone.com/BVCHh3Angenommen, Sie haben
Sie können verwenden
BigDecimal
oder ohne BigDecimal
mit beiden Lösungen
d == 9232.13
quelle
RoundingMode.HALF_UP
ist falsch. Probieren Sie es mit1.505
. Der richtige Weg ist zu verwendenBigDecimal.valueOf(d)
.Sie können die DecimalFormat-Klasse verwenden.
quelle
Double.valueOf()
gewählt wurdeDouble.parseDouble()
? DievalueOf()
Methode gibt einDouble
Objekt zurück, währendparseDouble()
eindouble
Grundelement zurückgegeben wird. Mit der Art und Weise, wie der aktuelle Code geschrieben wird, wenden Sie auch das automatische Entpacken auf die Rückgabe an, um ihn in das von IhrertwoDouble
Variablen erwartete Grundelement umzuwandeln, eine zusätzliche Bytecode-Operation. Ich würde die Antwort ändern, um sieparseDouble()
stattdessen zu verwenden .Double.parseDouble()
brauchtString
Input.In der Java- Anleitung von Real wird diese Lösung veröffentlicht, die auch für Versionen vor Java 1.6 kompatibel ist.
quelle
quelle
Math.floor(x + 0.5)
undMath.round(x)
@Milhous: Das Dezimalformat für die Rundung ist ausgezeichnet:
Ich würde hinzufügen, dass diese Methode sehr gut darin ist, einen tatsächlichen numerischen Rundungsmechanismus bereitzustellen - nicht nur visuell, sondern auch bei der Verarbeitung.
Hypothetisch: Sie müssen einen Rundungsmechanismus in ein GUI-Programm implementieren. Um die Genauigkeit / Präzision einer Ergebnisausgabe zu ändern, ändern Sie einfach das Caret-Format (dh innerhalb der Klammern). Damit:
würde als Ausgabe zurückkehren:
0.912385
würde als Ausgabe zurückkehren:
0.91239
würde als Ausgabe zurückkehren:
0.9124
[BEARBEITEN: Auch wenn das Caret-Format so ist ("# 0. #############") und Sie eine Dezimalzahl eingeben, z. B. 3.1415926, erzeugt DecimalFormat aus Gründen des Arguments keinen Müll ( zB nachgestellte Nullen) und wird zurückgegeben:
3.1415926
.. wenn Sie so geneigt sind. Zugegeben, es ist ein wenig ausführlich für den Geschmack einiger Entwickler - aber hey, es hat einen geringen Speicherbedarf während der Verarbeitung und ist sehr einfach zu implementieren.]Das Schöne an DecimalFormat ist also, dass es gleichzeitig das Erscheinungsbild der Zeichenfolge sowie die eingestellte Rundungsgenauigkeit behandelt. Ergo: Sie erhalten zwei Vorteile zum Preis einer Code-Implementierung. ;)
quelle
double
. Verwenden Sie BigDecimal oder ein anderes dezimalbasiertes Format.Hier ist eine Zusammenfassung dessen, was Sie verwenden können, wenn Sie das Ergebnis als String erhalten möchten:
DecimalFormat # setRoundingMode () :
BigDecimal # setScale ()
Hier ist ein Vorschlag, welche Bibliotheken Sie verwenden können, wenn Sie dies möchten
double
. Ich würde es jedoch nicht für die Zeichenfolgenkonvertierung empfehlen, da double möglicherweise nicht genau das darstellen kann, was Sie möchten (siehe z. B. hier ):Präzision von Apache Commons Math
Funktionen von Colt
Utils von Weka
quelle
Sie können die folgende Dienstprogrammmethode verwenden:
quelle
round(1.005,2);
oderround(0.50594724957626620092, 20);
Eine prägnante Lösung:
Siehe auch https://stackoverflow.com/a/22186845/212950 Vielen Dank an jpdymond für das Angebot.
quelle
Sie können BigDecimal verwenden
Siehe: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
quelle
Versuchen Sie Folgendes: org.apache.commons.math3.util.Precision.round (double x, int scale)
Siehe: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Die Homepage der Apache Commons Mathematics Library lautet: http://commons.apache.org/proper/commons-math/index.html
Die interne Implementierung dieser Methode lautet:
quelle
Da ich zu diesem Thema keine vollständige Antwort gefunden habe, habe ich eine Klasse zusammengestellt, die dies richtig handhaben sollte, mit Unterstützung für:
Die Verwendung ist ziemlich einfach :
(Für dieses Beispiel verwende ich ein benutzerdefiniertes Gebietsschema.)
Hier ist die Klasse :
quelle
Wenn Sie wirklich Dezimalzahlen für die Berechnung (und nicht nur für die Ausgabe) möchten, verwenden Sie kein binärbasiertes Gleitkommaformat wie double.
Ich verwende BigDecimal für Berechnungen, aber denke daran, dass es von der Größe der Zahlen abhängt, mit denen du es zu tun hast. In den meisten meiner Implementierungen ist das Parsen von Double oder Integer nach Long für Berechnungen mit sehr großen Zahlen ausreichend.
Tatsächlich habe ich kürzlich Parsed-to-Long verwendet, um genaue Darstellungen (im Gegensatz zu Hex-Ergebnissen) in einer GUI für Zahlen zu erhalten, die so groß sind wie ################### ################ Zeichen (als Beispiel).
quelle
Um dies zu erreichen, können wir diesen Formatierer verwenden:
oder:
Verwenden Sie diese Methode, um immer zwei Dezimalstellen zu erhalten:
Definieren dieser Werte:
Mit der Methode können wir diese Ergebnisse erhalten:
Demo online.
quelle
Nur für den Fall, dass noch jemand Hilfe benötigt. Diese Lösung funktioniert perfekt für mich.
gibt a
String
mit der gewünschten Ausgabe zurück.quelle
Ich stimme der gewählten Antwort zu
DecimalFormat
--- oder alternativBigDecimal
.Bitte lesen Sie zuerst das Update unten!
Wenn Sie jedoch den doppelten Wert runden und eindouble
Wertergebnis erhalten möchten , können Sie ihnorg.apache.commons.math3.util.Precision.round(..)
wie oben erwähnt verwenden. Die Implementierung verwendetBigDecimal
, ist langsam und erzeugt Müll.Eine ähnliche, aber schnelle undDoubleRounder
müllfreie Methode bietet das Dienstprogramm in der decimal4j-Bibliothek:Wird ausgegeben
Siehe https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Haftungsausschluss: Ich bin am decimal4j-Projekt beteiligt.
Update: Wie @iaforek hervorhob, gibt DoubleRounder manchmal kontraintuitive Ergebnisse zurück. Der Grund ist, dass es eine mathematisch korrekte Rundung durchführt. Zum Beispiel
DoubleRounder.round(256.025d, 2)
wird auf 256,02 abgerundet, weil der als 256,025d dargestellte Doppelwert etwas kleiner als der rationale Wert 256,025 ist und daher abgerundet wird.Anmerkungen:
BigDecimal(double)
Konstruktors sehr ähnlich (verwendet jedoch nichtvalueOf(double)
den String-Konstruktor).Aus diesen Gründen und allem, was oben in diesem Beitrag erwähnt wurde, kann ich die Verwendung von DoubleRounder nicht empfehlen .
quelle
Das folgende Codefragment zeigt, wie n Ziffern angezeigt werden. Der Trick besteht darin, die Variable pp auf 1 zu setzen, gefolgt von n Nullen. Im folgenden Beispiel hat der variable pp-Wert 5 Nullen, sodass 5 Ziffern angezeigt werden.
quelle
Wenn Sie
DecimalFormat
zum Konvertieren verwendendouble
,String
ist dies sehr einfach:RoundingMode
Abhängig vom gewünschten Verhalten stehen mehrere Aufzählungswerte zur Auswahl.quelle
Ich kam hierher und wollte nur eine einfache Antwort, wie man eine Zahl rundet. Dies ist eine ergänzende Antwort, um dies zu gewährleisten.
So runden Sie eine Zahl in Java
Der häufigste Fall ist zu verwenden
Math.round()
.Zahlen werden auf die nächste ganze Zahl gerundet. Ein
.5
Wert wird aufgerundet. Wenn Sie ein anderes Rundungsverhalten benötigen, können Sie eine der anderen mathematischen Funktionen verwenden. Siehe den Vergleich unten.runden
Wie oben angegeben, rundet dies auf die nächste ganze Zahl.
.5
Dezimalstellen runden ab. Diese Methode gibt eine zurückint
.Decke
Jeder Dezimalwert wird auf die nächste Ganzzahl aufgerundet. Es geht zur Decke . Diese Methode gibt a zurück
double
.Fußboden
Jeder Dezimalwert wird auf die nächste Ganzzahl abgerundet. Diese Methode gibt a zurück
double
.rint
Dies ähnelt dem Runden in diesen Dezimalwerten, die auf die nächste Ganzzahl gerundet werden. Doch im Gegensatz zu
round
,.5
runden Werte an die gerade ganze Zahl. Diese Methode gibt a zurückdouble
.quelle
Wenn Sie eine Technologie mit einem minimalen JDK verwenden. Hier ist ein Weg ohne Java-Bibliotheken:
quelle
DecimalFormat ist die beste Art der Ausgabe, aber ich bevorzuge es nicht. Ich mache das immer die ganze Zeit, weil es den doppelten Wert zurückgibt. Ich kann es also mehr als nur ausgeben.
ODER
Wenn Sie einen großen Dezimalstellenwert benötigen, können Sie stattdessen BigDecimal verwenden. Sowieso
.0
ist wichtig. Ohne sie ist die Rundung von 0,33333d5 0,33333 und nur 9 Stellen zulässig. Die zweite Funktion ohne.0
Probleme mit 0.30000 return 0.30000000000000004.quelle
Hier ist meine Antwort:
quelle
Nachdem ich die meisten Antworten gelesen hatte, stellte ich fest, dass die meisten nicht präzise sind. Tatsächlich
BigDecimal
scheint die Verwendung die beste Wahl zu sein. Wenn Sie jedoch nicht verstehen, wie dasRoundingMode
funktioniert, verlieren Sie unvermeidlich an Präzision. Ich habe das herausgefunden, als ich mit großen Zahlen in einem Projekt gearbeitet habe, und dachte, es könnte anderen helfen, Probleme beim Runden von Zahlen zu haben. Zum Beispiel.Sie würden erwarten,
1363.28
als Ausgabe zu erhalten, aber Sie werden am Ende mit1363.27
, was nicht erwartet wird, wenn Sie nicht wissen, was dasRoundingMode
tut. Wenn Sie sich also die Oracle-Dokumente ansehen , finden Sie die folgende Beschreibung fürRoundingMode.HALF_UP
.Als wir das wussten, stellten wir fest, dass wir keine exakte Rundung erhalten, es sei denn, wir möchten in Richtung des nächsten Nachbarn runden . Um eine angemessene Runde zu erreichen, müssten wir also von der
n-1
Dezimalstelle zu den gewünschten Dezimalstellen schleifen . Zum Beispiel.Dies wird uns am Ende den erwarteten Output geben, der sein würde
1363.28
.quelle
Wobei dp = Dezimalstelle ist und der Wert ein Doppel ist.
quelle
1.0
fürvalue = 1.005
unddp = 2
. Verwenden Sie dies stattdessen.Beachten Sie, dass String.format () und DecimalFormat Zeichenfolgen mit dem Standardgebietsschema erstellen. Sie können also eine formatierte Zahl mit Punkt oder Komma als Trennzeichen zwischen Ganzzahl- und Dezimalteilen schreiben. Um sicherzustellen, dass der gerundete String das gewünschte Format hat, verwenden Sie java.text.NumberFormat wie folgt:
Wird in englischer Sprache gedruckt (unabhängig von Ihrer Ländereinstellung): 0,99 123,57 123,00
Das Beispiel stammt von Farenda - wie man Double korrekt in String konvertiert .
quelle
Im Allgemeinen erfolgt die Rundung durch Skalierung:
round(num / p) * p
quelle