it-swarm.com.de

Doppelter Wert zum Abrunden in Java

Ich habe einen doppelten Wert = 1.068879335 Ich möchte es mit nur zwei Dezimalwerten wie 1,07 aufrunden.

Ich habe es so versucht

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value);
double finalValue = Double.parseDouble(formate) ;

dies gibt mir die folgende Ausnahme 

Java.lang.NumberFormatException: For input string: "1,07"
     at Sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.Java:1224)
     at Java.lang.Double.parseDouble(Double.Java:510)

kann mir jemand sagen, was mit meinem Code falsch ist. 

endlich brauche ich den finalValue = 1.07;

34
jimmy

Beachten Sie das Komma in Ihrer Zeichenfolge: "1,07". DecimalFormat verwendet eine ländereinstellungsspezifische Trennzeichenfolge, während Double.parseDouble() dies nicht tut. Wenn Sie in einem Land leben, in dem das Dezimaltrennzeichen "," ist, können Sie Ihre Zahl nicht zurücksuchen.

Sie können jedoch dieselbe DecimalFormat verwenden, um es zurückzuspielen:

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value); 
double finalValue = (Double)df.parse(formate) ;

Sie sollten dies jedoch stattdessen tun:

double finalValue = Math.round( value * 100.0 ) / 100.0;

Hinweis: Wie bereits erwähnt, sollten Sie Fließkommazahlen nur verwenden, wenn Sie keine genaue Kontrolle der Genauigkeit benötigen. (Finanzielle Berechnungen sind das wichtigste Beispiel, wann nicht sie zu verwenden sind.)

76
biziclop

Live @ Sergejys Lösung, jedoch mit ganzzahliger Division.

double value = 23.8764367843;
double rounded = (double) Math.round(value * 100) / 100;
System.out.println(value +" rounded is "+ rounded);

druckt

23.8764367843 rounded is 23.88

BEARBEITEN: Wie Sergey betont, sollte es keinen Unterschied geben zwischen Multiplikation von Double * Int und Double * Double und Division von Double/Int und Double/Double. Ich kann kein Beispiel finden, bei dem das Ergebnis anders ist. Auf x86/x64 und anderen Systemen gibt es jedoch eine spezielle Maschinencodeanweisung für gemischte doppelte, int-Werte, die meiner Meinung nach von der JVM verwendet werden.

for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100) / 100;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,int operations %,d%n", time);
}
for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100.0) / 100.0;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,double operations %,d%n", time);
}

Drucke

double,int operations 613,552,212
double,int operations 661,823,569
double,int operations 659,398,960
double,int operations 659,343,506
double,int operations 653,851,816
double,int operations 645,317,212
double,int operations 647,765,219
double,int operations 655,101,137
double,int operations 657,407,715
double,int operations 654,858,858
double,int operations 648,702,279
double,double operations 1,178,561,102
double,double operations 1,187,694,386
double,double operations 1,184,338,024
double,double operations 1,178,556,353
double,double operations 1,176,622,937
double,double operations 1,169,324,313
double,double operations 1,173,162,162
double,double operations 1,169,027,348
double,double operations 1,175,080,353
double,double operations 1,182,830,988
double,double operations 1,185,028,544
18
Peter Lawrey

Das Problem ist, dass Sie ein lokalisierendes Formatierungsprogramm verwenden, das einen ländereinstellungsspezifischen Dezimalpunkt generiert, der in Ihrem Fall "," ist. Double.parseDouble () erwartet jedoch ein nicht lokalisiertes doppeltes Literal. Sie können Ihr Problem lösen, indem Sie eine ländereinstellungsspezifische Methode zum Analysieren verwenden oder das Gebietsschema Ihres Formatierers in etwas ändern, das "." als Dezimalpunkt. Oder noch besser: Vermeiden Sie unnötige Formatierungen, indem Sie Folgendes verwenden:

double rounded = (double) Math.round(value * 100.0) / 100.0;
6
Sergei Tachenov

Mit dem, was Sie versuchen, ist grundsätzlich etwas nicht in Ordnung. Binäre Gleitkommawerte haben keine haben Dezimalstellen. Sie können einen Wert nicht sinnvoll auf eine bestimmte Anzahl von Dezimalstellen runden, da die meisten "runden" Dezimalwerte nicht einfach als binärer Bruch dargestellt werden können. Deshalb sollte man niemals float oder double verwenden, um Geld darzustellen.

Wenn Sie also Dezimalstellen in Ihrem Ergebnis wünschen, muss dieses Ergebnis entweder eine String (die Sie bereits mit der DecimalFormat erhalten haben) oder eine BigDecimal (die eine setScale()-Methode hat, die genau das tut, was Sie möchten) haben. Andernfalls kann das Ergebnis nicht das sein, was Sie möchten.

Lesen Sie Der Gleitkomma-Leitfaden für weitere Informationen.

4

Versuchen Sie Folgendes: Org.Apache.commons.math3.util.Precision.round (doppeltes X, int. Skalierung)

Siehe: http://commons.Apache.org/proper/commons-math/apidocs/org/Apache/commons/math3/util/Precision.html

Die Homepage der Mathematikbibliothek von Apache Commons lautet: http://commons.Apache.org/proper/commons-math/index.html

Die interne Implementierung dieser Methode lautet:

public static double round(double x, int scale) {
    return round(x, scale, BigDecimal.ROUND_HALF_UP);
}

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new BigDecimal
               (Double.toString(x))
               .setScale(scale, roundingMethod))
               .doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}
2
Li Ying

Sie können versuchen, ein neues DecimalFormat zu definieren und es als Doppelergebnis für eine neue Doppelvariable zu verwenden.

Beispiel gegeben, damit Sie verstehen, was ich gerade gesagt habe.

double decimalnumber = 100.2397;
DecimalFormat dnf = new DecimalFormat( "#,###,###,##0.00" );
double roundednumber = new Double(dnf.format(decimalnumber)).doubleValue();
1
Markku
double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

    TotalPrice = Double.valueOf(format_2Places.format(TotalPrice));
1
DeltaCap019

Dies ist auf die angeforderte Weise nicht möglich, da es Zahlen mit zwei Nachkommastellen gibt, die mit IEEE-Gleitkommazahlen nicht exakt ausgedrückt werden können (beispielsweise 1/10 = 0,1 kann nicht als Double oder Float ausgedrückt werden). Die Formatierung sollte immer als letzter Schritt erfolgen, bevor das Ergebnis dem Benutzer angezeigt wird.

Ich denke, Sie fragen, weil Sie mit monetären Werten umgehen wollen. Es gibt keine Möglichkeit, dies mit Fließkommazahlen zuverlässig zu tun. Sie sollten in Betracht ziehen, auf Festkomma-Arithmetik umzusteigen. Dies bedeutet wahrscheinlich, dass alle Berechnungen in "Cent" statt in "Dollar" ausgeführt werden.

1
Waldheinz

Wenn Sie DecimalFormat nicht verwenden möchten (z. B. aufgrund seiner Effizienz) und eine allgemeine Lösung möchten, können Sie auch die folgende Methode mit skalierter Rundung verwenden:

public static double roundToDigits(double value, int digitCount) {
    if (digitCount < 0)
        throw new IllegalArgumentException("Digit count must be positive for rounding!");

    double factor = Math.pow(10, digitCount);
    return (double)(Math.round(value * factor)) / factor;
}
0
Keplerian

Sie können Format wie hier verwenden,

  public static double getDoubleValue(String value,int digit){
    if(value==null){
        value="0";
     }
    double i=0;
     try {
         DecimalFormat digitformat = new DecimalFormat("#.##");
         digitformat.setMaximumFractionDigits(digit);
        return Double.valueOf(digitformat.format(Double.parseDouble(value)));

    } catch (NumberFormatException numberFormatExp) {
        return i;   
    }
}
0
Knowledge Serve