Jak sformatować liczbę w Javie?

114

Jak sformatować liczbę w Javie?
Jakie są „sprawdzone metody”?

Czy przed sformatowaniem będę musiał zaokrąglić liczbę?

32.302342342342343 => 32.30

.7323 => 0.73

itp.

ScArcher2
źródło

Odpowiedzi:

124

Z tego wątku można to zrobić na różne sposoby:

double r = 5.1234;
System.out.println(r); // r is 5.1234

int decimalPlaces = 2;
BigDecimal bd = new BigDecimal(r);

// setScale is immutable
bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP);
r = bd.doubleValue();

System.out.println(r); // r is 5.12

f = (float) (Math.round(n*100.0f)/100.0f);

DecimalFormat df2 = new DecimalFormat( "#,###,###,##0.00" );
double dd = 100.2397;
double dd2dec = new Double(df2.format(dd)).doubleValue();

// The value of dd2dec will be 100.24

DecimalFormat () wydaje się być najbardziej dynamiczny sposób to zrobić, i to jest bardzo łatwe do zrozumienia podczas czytania kodu innych.

Espo
źródło
Dzięki za to wyjaśnienie. Jednak Intellij zaleca użycie Double.valueOfzamiast new Double(number).doubleValue(). Ostatnią linijką ostatniego przykładu byłoby zatemdouble dd2dec = Double.valueOf(df2.format(dd));
kumaheiyama,
Wzorzec DecimalFormat w tej odpowiedzi jest doskonały dla Stanów Zjednoczonych, ale nieprawidłowy w większości innych lokalizacji na całym świecie. Znak grupowania (przecinek w USA, ale spacja lub kropka w innych językach), rozmiar grupowania (trójki w USA i większość ustawień, ale inny w Indiach), znak dziesiętny (kropka w USA, ale przecinek w innych językach) . Prawidłowy sposób uzyskania instancji DecimalFormat to: DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance (locale)
vonWippersnap
74

Ty i String.format()będziesz nowymi najlepszymi przyjaciółmi!

https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#syntax

 String.format("%.2f", (double)value);
Jeff Atwood
źródło
29
Ta odpowiedź nie spotkałaby się z tak wieloma pozytywnymi opiniami, gdyby pochodziła od kogokolwiek innego. String.formatsłuży do formatowania łańcuchów, a nie liczb.
Dónal
4
Właściwie String.format jest podobny do printf w C. Może formatować kilka rodzajów typów danych.
cesarse
3
Jeśli chcesz przekonwertować zaokrągloną wartość na ciąg, jest to jeden ze sposobów. Inny używa DecimalFormat. I DecimalFormatjest nieco szybszy niż String.format. Prosty System.currentTimeMillisdiff to pokazuje.
manikanta,
To tylko dla wartości ciągu
T8Z,
To najlepsza odpowiedź. Chociaż liczba cyfr po przecinku jest całkowicie specyficzna dla domeny, liczby muszą być wyświetlane w sposób uwzględniający ustawienia regionalne. String.format () używa poprawnych symboli liczbowych i znaku dziesiętnego dla domyślnych ustawień narodowych. Jeszcze lepiej byłoby przekazać wymagane locale jako pierwszy parametr do format (), aby było to jawne.
vonWippersnap,
14

Należy pamiętać, że klasy, które pochodzą od NumberFormat (i większość innych elementów podrzędnych Format) nie są synchronizowane. Powszechną (ale niebezpieczną) praktyką jest tworzenie obiektów formatu i przechowywanie ich w statycznych zmiennych w klasie util. W praktyce będzie działać prawie zawsze, dopóki nie zacznie odczuwać znacznego obciążenia.

Robert J. Walker
źródło
1
Dziękuję Ci! Właśnie mnie uratowałeś.
David Thielen
11

Okrągłe liczby, tak. To jest główne przykładowe źródło .

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */ 


import java.util.*;
import java.text.*;

public class DecimalFormatDemo {

    static public void customFormat(String pattern, double value ) {
        DecimalFormat myFormatter = new DecimalFormat(pattern);
        String output = myFormatter.format(value);
        System.out.println(value + "  " + pattern + "  " + output);
    }

    static public void localizedFormat(String pattern, double value,                                       Locale loc ) {
        NumberFormat nf = NumberFormat.getNumberInstance(loc);
        DecimalFormat df = (DecimalFormat)nf;
        df.applyPattern(pattern);
        String output = df.format(value);
        System.out.println(pattern + "  " + output + "  " + loc.toString());
    }

    static public void main(String[] args) {

        customFormat("###,###.###", 123456.789);
        customFormat("###.##", 123456.789);
        customFormat("000000.000", 123.78);
        customFormat("$###,###.###", 12345.67);
        customFormat("\u00a5###,###.###", 12345.67);

        Locale currentLocale = new Locale("en", "US");

        DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols(currentLocale);
        unusualSymbols.setDecimalSeparator('|');
        unusualSymbols.setGroupingSeparator('^');
        String strange = "#,##0.###";
        DecimalFormat weirdFormatter = new DecimalFormat(strange, unusualSymbols);
        weirdFormatter.setGroupingSize(4);
        String bizarre = weirdFormatter.format(12345.678);
        System.out.println(bizarre);

        Locale[] locales = {
            new Locale("en", "US"),
            new Locale("de", "DE"),
            new Locale("fr", "FR")
        };

        for (int i = 0; i < locales.length; i++) {
            localizedFormat("###,###.###", 123456.789, locales[i]);
        }
     }
 }
Vinko Vrsalovic
źródło
8

Spróbuj tego:

String.format("%.2f", 32.302342342342343);

Proste i wydajne.

Łodzik
źródło
4

W bibliotece standardowej istnieją dwa podejścia. Jednym z nich jest użycie java.text.DecimalFormat. Inne, bardziej tajemnicze metody (String.format, PrintStream.printf itp.) Oparte na java.util.Formatter powinny zadowolić programistów C (ish).

Tom Hawtin - haczyk
źródło
2

Jak zauważył Robert w swojej odpowiedzi: DecimalFormat nie jest ani synchronizowany, ani API nie gwarantuje bezpieczeństwa wątków (może to zależeć od używanej wersji JVM / dostawcy).

Zamiast tego użyj Spring's Numberformatter , który jest bezpieczny dla wątków.

Stefan Haberl
źródło
2
public static void formatDouble(double myDouble){
 NumberFormat numberFormatter = new DecimalFormat("##.000");
 String result = numberFormatter.format(myDouble);
 System.out.println(result);
}

Na przykład, jeśli wartość double przekazana do metody formatDouble () to 345,9372, wynikiem będzie następujący: 345,937 Podobnie, jeśli do metody zostanie przekazana wartość .7697, wynikiem będzie: .770

snr
źródło