Frage Wie man eine Zahl auf n Dezimalstellen in Java rundet
Was ich möchte, ist eine Methode, um ein Double in eine Zeichenkette zu konvertieren, die mit der Half-Up-Methode rundet - d. H. Wenn die zu gerundete Dezimalzahl 5 ist, wird sie immer auf die vorherige Zahl aufgerundet. Dies ist die Standardmethode der Rundung, die die meisten Menschen in den meisten Situationen erwarten.
Ich möchte auch, dass nur signifikante Ziffern angezeigt werden - d. H. Es sollte keine abschließenden Nullen geben.
Ich weiß, eine Methode, dies zu tun, ist die Verwendung der String.format
Methode:
String.format("%.5g%n", 0.912385);
kehrt zurück:
0.91239
Das ist großartig, aber es zeigt 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 der DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
kehrt zurück:
0.91238
Wie Sie jedoch sehen können, wird hier eine halbrunde Rundung verwendet. Das heißt, es wird abgerundet, wenn die vorherige Ziffer gerade ist. Was ich möchte ist das:
0.912385 -> 0.91239
0.912300 -> 0.9123
Was ist der beste Weg, dies in Java zu erreichen?
1021
2017-09-30 16:01
Ursprung
Antworten:
Benutzen setRoundingMode
Stellen Sie die RoundingMode
explizit, um Ihr Problem mit der Half-Even-Runde zu behandeln, dann verwenden Sie das Formatmuster für Ihre gewünschte Ausgabe.
Beispiel:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gibt die Ausgabe:
12
123.1235
0.23
0.1
2341234.2125
583
2017-09-30 16:14
Angenommen value
ist ein double
, du kannst tun:
(double)Math.round(value * 100000d) / 100000d
Das ist für 5-stellige Genauigkeit. Die Anzahl der Nullen gibt die Anzahl der Dezimalstellen an.
397
2017-09-30 16:07
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
Ich werde dir ein BigDecimal
. Um die Saite rauszuholen, rufen Sie sie einfach an BigDecimal
ist es toString
Methode oder die toPlainString
Methode für Java 5+ für eine einfache Formatzeichenfolge.
Beispielprogramm:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
164
2017-09-30 18:33
Sie können auch die
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
um sicher zu stellen, dass Sie die abschließenden Nullen haben.
98
2017-09-30 16:58
Wie einige andere bemerkt haben, ist die richtige Antwort, entweder zu verwenden DecimalFormat
oder BigDecimal
. Gleitkomma nicht haben Nachkommastellen, so dass Sie nicht auf eine bestimmte Anzahl von ihnen an erster Stelle runden / abschneiden können. Sie müssen in einer Dezimalzahl arbeiten, und genau das tun diese beiden Klassen.
Ich poste den folgenden Code als ein Gegenbeispiel zu allen Antworten in diesem Thread und tatsächlich überall in StackOverflow (und anderswo), die Multiplikation gefolgt von Abschneiden gefolgt von Division empfehlen. Den Verfechtern dieser Technik obliegt es zu erklären, warum der folgende Code in über 92% der Fälle die falsche Ausgabe liefert.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Ausgabe dieses Programms:
10001 trials 9251 errors
BEARBEITEN: Um einige der folgenden Kommentare zu beantworten, habe ich den Modulo-Teil der Testschleife mit Hilfe von BigDecimal
und new MathContext(16)
für die Moduloperation wie folgt:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Ergebnis:
10001 trials 4401 errors
75
2017-10-02 03:18
Angenommen, du hast
double d = 9232.129394d;
Sie können verwenden BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
oder ohne BigDecimal
d = Math.round(d*100)/100.0d;
mit beiden Lösungen d == 9232.13
71
2018-01-28 09:52
Sie können die DecimalFormat-Klasse verwenden.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
52
2017-09-29 07:01
Real's Java Anleitung Beiträge Diese Lösung, die auch für Versionen vor Java 1.6 kompatibel ist.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
34
2017-09-01 11:14
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
30
2017-09-30 16:09
@Milhous: Das Dezimalformat für das Runden ist ausgezeichnet:
Sie können auch die
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
um sicher zu stellen, dass Sie die abschließenden Nullen haben.
Ich möchte hinzufügen, dass diese Methode sehr gut darin ist, ein tatsächliches zu liefern
numerische, Rundungsmechanismus - nicht nur visuell, sondern auch bei der Verarbeitung.
Hypothetisch: Sie müssen einen Rundungsmechanismus in eine GUI implementieren
Programm. Um die Genauigkeit / Genauigkeit einer Ergebnisausgabe einfach zu ändern
Ändern Sie das Caret-Format (d. h. innerhalb der Klammern). Damit:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
würde als Ausgabe zurückkehren: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
würde als Ausgabe zurückkehren: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
würde als Ausgabe zurückkehren: 0.9124
[EDIT: auch wenn das Caret-Format so ist ("# 0. ############") und du
Geben Sie eine Dezimalzahl ein, z. 3.1415926, um des Arguments willen, DecimalFormat
erzeugt keinen Müll (z. B. nachgestellte Nullen) und gibt zurück:
3.1415926
.. wenn du so geneigt bist. Zugegeben, es ist ein wenig wortreich
für den Geschmack einiger Entwickler - aber hey, es hat einen geringen Speicherbedarf
während der Verarbeitung und ist sehr einfach zu implementieren.]
Im Wesentlichen ist die Schönheit von DecimalFormat, dass es gleichzeitig die Zeichenfolge verarbeitet
Aussehen - sowie das Niveau der Rundungsgenauigkeit eingestellt. Ergo: du
erhalten Sie zwei Vorteile für den Preis einer Code-Implementierung. ;)
27
2017-07-03 15:50
Sie könnten die folgende Hilfsmethode verwenden:
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
17
2018-04-27 15:56