Jak zaokrąglać liczbę do n miejsc po przecinku w Javie

To, co chciałbym, to metoda konwersji podwójnego na ciąg, który zaokrągla się metodą half-up - tzn. jeśli liczba dziesiętna, która ma być zaokrąglona, wynosi 5, zawsze zaokrągla się do poprzedniej liczby. Jest to standardowa metoda zaokrąglania, której większość ludzi oczekuje w większości sytuacji.

Chciałbym również, aby wyświetlane były tylko znaczące cyfry - tzn. nie powinno być żadnych końcowych zer.

Wiem, że jedną z metod jest użycie String.format "metoda": {]}

String.format("%.5g%n", 0.912385);

Zwraca:

0.91239

Co jest świetne, jednak zawsze wyświetla liczby z 5 miejscami po przecinku, nawet jeśli nie są znaczące:

String.format("%.5g%n", 0.912300);

Zwraca:

0.91230

Inną metodą jest użycie DecimalFormatter:

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

Zwraca:

0.91238

Jednak, jak widać, używa pół-parzystego zaokrąglenia. Oznacza to, że zaokrągli się w dół, jeśli poprzednia cyfra jest parzysta. Ja bym chciał:

0.912385 -> 0.91239
0.912300 -> 0.9123

Jaki jest najlepszy sposób na osiągnięcie tego w Javie?

Author: Taryn, 2008-09-30

29 answers

Użycie setRoundingMode, set the RoundingMode jawnie, aby rozwiązać problem z half-even round, następnie użyj wzorca formatu dla wymaganego wyjścia.

Przykład:

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));
}

Daje wyjście:

12
123.1235
0.23
0.1
2341234.2125
 601
Author: curtisk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-03 13:10:53

Zakładając, że value jest double, możesz zrobić:

(double)Math.round(value * 100000d) / 100000d

To 5 cyfr precyzji. Liczba zer oznacza liczbę miejsc po przecinku.

 401
Author: asterite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-16 12:17:03
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

Da ci BigDecimal. Aby uzyskać ciąg znaków, po prostu wywołaj tę metodę BigDecimal toString lub metodę toPlainString dla Java 5+ dla zwykłego ciągu znaków.

Przykładowy program:

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
Author: MetroidFan2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 08:00:31

Możesz również użyć

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

Aby upewnić się, że masz trailing 0 ' s.

 100
Author: Milhous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-30 16:58:12

Jak zauważyli inni, poprawną odpowiedzią jest użycie DecimalFormat lub BigDecimal. Zmiennoprzecinkowy nie ma miejsc po przecinku, więc nie można zaokrąglić/obciąć do określonej liczby z nich w pierwszej kolejności. Musisz pracować w radix dziesiętny, i to jest to, co te dwie klasy zrobić.

Zamieszczam poniższy kod jako kontr-przykład do wszystkich odpowiedzi w tym wątku i rzeczywiście w całym StackOverflow (i gdzie indziej), które zalecają mnożenie, a następnie okrojenie, po którym następuje podział. Zwolennicy tej techniki powinni wyjaśnić, dlaczego poniższy kod generuje błędne dane wyjściowe w ponad 92% przypadków.

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");
    }
}

Wyjście tego programu:

10001 trials 9251 errors

EDIT: aby odnieść się do niektórych komentarzy poniżej przerobiłem część modułu pętli testowej używając BigDecimal i new MathContext(16) dla operacji modułu w następujący sposób:

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");
}

Wynik:

10001 trials 4401 errors
 75
Author: user207421,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-18 03:53:47

Załóżmy, że masz

double d = 9232.129394d;

Możesz użyć BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

Lub bez BigDecimal

d = Math.round(d*100)/100.0d;

Z obu rozwiązań d == 9232.13

 72
Author: user593581,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-14 22:30:33

Możesz użyć klasy DecimalFormat.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));
 52
Author: JibW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-29 07:01:59

Real ' S Java How-To posts To rozwiązanie, które jest również kompatybilne z wersjami przed Javą 1.6.

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
 34
Author: Ovesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-01 11:14:32
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
 30
Author: Chris Cudmore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-30 16:09:26

@Milhous: format dziesiętny dla zaokrąglania jest doskonały:

Możesz również użyć

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

Aby upewnić się, że masz trailing 0 ' s.

[[8]} dodam, że metoda ta jest bardzo dobra w dostarczaniu rzeczywistego numeryczny mechanizm zaokrąglania-nie tylko wizualnie, ale także podczas przetwarzania.

Hipotetycznie: musisz zaimplementować mechanizm zaokrąglania do GUI program. Aby zmienić dokładność / precyzję wyniku po prostu zmień format karetki (tj. w nawiasach). Tak że:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

Zwróci jako wyjście: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

Zwróci jako wyjście: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

Zwróci jako wyjście: 0.9124

[EDIT: również jeśli format karetki jest taki ("#0.###########") I ty 3.1415926, dla argumentu, DecimalFormat nie generuje żadnych śmieci (np. końcowe zera) i zwróci: 3.1415926 .. jeśli jesteś taka skłonna. Przyznaję, to trochę gadatliwe. dla upodobania niektórych dev ' ów - ale ma małą pamięć. podczas przetwarzania i jest bardzo łatwy do wdrożenia.]

Więc zasadniczo, piękno DecimalFormat jest to, że jednocześnie obsługuje ciąg wygląd - jak również poziom precyzji zaokrąglania ustawiony. Ergo: ty uzyskaj dwie korzyści w cenie jednej implementacji kodu. ;)

 27
Author: Ivan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-03 19:55:34

Możesz użyć następującej metody użytkowej -

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}
 17
Author: Amit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-27 15:56:25

Oto podsumowanie tego, czego możesz użyć, jeśli chcesz, aby wynik był ciągiem znaków:

  1. DecimalFormat # setround():

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
    
  2. BigDecimal()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
    

Oto sugestia, jakich bibliotek możesz użyć, jeśli chcesz double w rezultacie. Nie polecałbym go jednak do konwersji łańcuchów, ponieważ double może nie być w stanie dokładnie reprezentować tego, co chcesz (patrz np. tutaj):

  1. Precision from Apache Commons Math

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  2. Funkcje z Colt

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  3. Utils from Weka

    double rounded = Utils.roundDouble(0.912385, 5)
    
 15
Author: Mifeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:47

Zwięzłe rozwiązanie:

   public static double round(double value, int precision) {
      int scale = (int) Math.pow(10, precision);
      return (double) Math.round(value * scale) / scale;
  }

Zobacz też: https://stackoverflow.com/a/22186845/212950 Podziękowania dla jpdymond za zaoferowanie tego.

 9
Author: MAbraham1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-26 14:41:08

Możesz użyć BigDecimal

BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);

Zobacz: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

 8
Author: Easwaramoorthy K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-22 09:49:35

Spróbuj tego: org.Apacz.commons.math3.util.Precyzja.round (double x, int scale)

Zobacz: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html

Wewnętrzna implementacja tej metody to:

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;
        }
    }
}
 7
Author: Li Ying,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-20 05:04:07

Ponieważ nie znalazłem pełnej odpowiedzi na ten temat, ułożyłem klasę, która powinna sobie z tym poradzić poprawnie, z obsługą dla:

  • formatowanie : łatwo formatować podwójny ciąg znaków z określoną liczbą miejsc po przecinku
  • Parsing : parsuje sformatowaną wartość z powrotem do podwójnego
  • Locale : Formatuj i analizuj używając domyślnego locale
  • notacja wykładnicza : zacznij używać notacji wykładniczej po pewnym próg

Użycie jest dość proste :

(dla tego przykładu używam niestandardowych ustawień regionalnych)

public static final int DECIMAL_PLACES = 2;

NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);

String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"

double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345

Oto klasa :

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;

public class NumberFormatter {

    private static final String SYMBOL_INFINITE           = "\u221e";
    private static final char   SYMBOL_MINUS              = '-';
    private static final char   SYMBOL_ZERO               = '0';
    private static final int    DECIMAL_LEADING_GROUPS    = 10;
    private static final int    EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
    private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation

    private DecimalFormat decimalFormat;
    private DecimalFormat decimalFormatLong;
    private DecimalFormat exponentialFormat;

    private char groupSeparator;

    public NumberFormatter(int decimalPlaces) {
        configureDecimalPlaces(decimalPlaces);
    }

    public void configureDecimalPlaces(int decimalPlaces) {
        if (decimalPlaces <= 0) {
            throw new IllegalArgumentException("Invalid decimal places");
        }

        DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
        separators.setMinusSign(SYMBOL_MINUS);
        separators.setZeroDigit(SYMBOL_ZERO);

        groupSeparator = separators.getGroupingSeparator();

        StringBuilder decimal = new StringBuilder();
        StringBuilder exponential = new StringBuilder("0.");

        for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
            decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
        }

        for (int i = 0; i < decimalPlaces; i++) {
            decimal.append("#");
            exponential.append("0");
        }

        exponential.append("E0");

        decimalFormat = new DecimalFormat(decimal.toString(), separators);
        decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
        exponentialFormat = new DecimalFormat(exponential.toString(), separators);

        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
        exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
    }

    public String format(double value) {
        String result;
        if (Double.isNaN(value)) {
            result = "";
        } else if (Double.isInfinite(value)) {
            result = String.valueOf(SYMBOL_INFINITE);
        } else {
            double absValue = Math.abs(value);
            if (absValue >= 1) {
                if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
                    value = Math.floor(value);
                    result = exponentialFormat.format(value);
                } else {
                    result = decimalFormat.format(value);
                }
            } else if (absValue < 1 && absValue > 0) {
                if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
                    result = decimalFormat.format(value);
                    if (result.equalsIgnoreCase("0")) {
                        result = decimalFormatLong.format(value);
                    }
                } else {
                    result = exponentialFormat.format(value);
                }
            } else {
                result = "0";
            }
        }
        return result;
    }

    public String formatWithoutGroupSeparators(double value) {
        return removeGroupSeparators(format(value));
    }

    public double parse(String value, double defValue) {
        try {
            return decimalFormat.parse(value).doubleValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return defValue;
    }

    private String removeGroupSeparators(String number) {
        return number.replace(String.valueOf(groupSeparator), "");
    }

}
 6
Author: Andrei Lupsa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 22:39:16

Na wypadek, gdyby ktoś jeszcze potrzebował pomocy. To rozwiązanie sprawdza się u mnie doskonale.

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();

}

Zwraca {[1] } z żądanym wyjściem.

 5
Author: Asher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-03 11:43:00

Jeśli naprawdę chcesz liczby dziesiętne do obliczeń (i nie tylko dla danych wyjściowych), nie używaj binarnego formatu zmiennoprzecinkowego, takiego jak double.

Use BigDecimal or any other decimal-based format.

Używam BigDecimal do obliczeń, ale pamiętaj, że zależy to od wielkości liczby, z którymi masz do czynienia. W większości moich implementacji znajduję parsowanie z podwójnego lub liczba całkowita do Long wystarcza do bardzo dużych obliczeń liczbowych.

In fact, I ' ve ostatnio używane parsed-to-Long, aby uzyskać dokładne reprezentacje (w przeciwieństwie do wyników hex) w GUI dla liczb tak dużych jak ################################# postacie (jako przykład).

 5
Author: Ivan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-30 18:33:04

Jeśli używasz DecimalFormat do konwersji double na String, jest to bardzo proste:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

Istnieje kilka wartości RoundingMode do wyboru, w zależności od wymaganego zachowania.

 4
Author: Drew Noakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-28 11:54:36

Poniższy fragment kodu pokazuje, jak wyświetlić n cyfr. Sztuczka polega na ustawieniu zmiennej pp na 1, po której następuje N zer. W poniższym przykładzie zmienna pp value ma 5 zer, więc wyświetlone zostanie 5 cyfr.

double pp = 10000;

double myVal = 22.268699999999967;
String needVal = "22.2687";

double i = (5.0/pp);

String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
 3
Author: Jasdeep Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-12 13:09:52

Przyszedłem tu po prostą odpowiedź, jak zaokrąglić liczbę. Jest to odpowiedź uzupełniająca, aby to zapewnić.

Jak zaokrąglać liczbę w Javie

Najczęstszym przypadkiem jest użycie Math.round().

Math.round(3.7) // 4

Liczby są zaokrąglane do najbliższej liczby całkowitej. Wartość .5 jest zaokrąglana w górę. Jeśli potrzebujesz innego zachowania zaokrąglania niż to, możesz użyć jednej z innych funkcji Math . Zobacz porównanie poniżej.

Runda

Jako podane powyżej, to zaokrągla się do najbliższej liczby całkowitej. .5 liczby dziesiętne zaokrąglają się. Ta metoda zwraca int.

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4

Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4

Ceil

Każda wartość dziesiętna jest zaokrąglana do następnej liczby całkowitej. To idzie do ceil ing. Metoda ta zwraca double.

Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0

Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0

Podłoga

Każda wartość dziesiętna jest zaokrąglana w dół do następnej liczby całkowitej. Metoda ta zwraca double.

Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0

Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0

Rint

To jest podobne do rundy w tym wartości dziesiętne zaokrąglają się do najbliższej liczby całkowitej. Jednak w przeciwieństwie do round, .5 wartości zaokrąglają się do parzystej liczby całkowitej. Metoda ta zwraca double.

Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***

Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
 3
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-20 14:42:47

Zgadzam się z wybraną odpowiedzią na użycie DecimalFormat - - - lub alternatywnie BigDecimal.

Przeczytaj najpierw Update poniżej!

Jeśli jednak zrobisz chcesz zaokrąglać podwójną wartość i uzyskać wynik double, możesz użyć org.apache.commons.math3.util.Precision.round(..), Jak wspomniano powyżej. Implementacja używa BigDecimal, jest powolna i tworzy śmieci.

Podobna, ale szybka i pozbawiona śmieci metoda jest dostarczana przez narzędzie DoubleRounder w bibliotece decimal4j:

 double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

Will wyjście

 0.667
 0.666
 1000.0
 9.00800700601E10

Zobacz https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

Zrzeczenie się: jestem zaangażowany w projekt decimal4j.

Aktualizacja: Jak zauważył @iaforek, DoubleRounder czasami zwraca sprzeczne wyniki. Powodem jest to, że wykonuje matematycznie poprawne zaokrąglanie. Na przykład DoubleRounder.round(256.025d, 2) zostanie zaokrąglone w dół do 256.02, ponieważ Podwójna wartość reprezentowana jako 256.025 d jest nieco mniejsza niż wartość racjonalna 256.025 i w związku z tym zostanie zaokrąglona w dół.

Uwagi:

  • to zachowanie jest bardzo podobne do konstruktora BigDecimal(double) (ale nie do valueOf(double), który używa konstruktora łańcuchowego).
  • Problem można obejść za pomocą podwójnego zaokrąglenia do większej precyzji, ale jest to skomplikowane i nie będę tu wchodzić w szczegóły]}

Z tych powodów i wszystkich wymienionych powyżej w tym poście nie mogę polecić aby użyć DoubleRounder .

 3
Author: marco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-11 23:42:35

DecimalFormat jest najlepszym sposobem na wyjście, ale nie wolę go. Zawsze robię to cały czas, ponieważ Zwraca podwójną wartość. Więc mogę użyć go więcej niż tylko wyjście.

Math.round(selfEvaluate*100000d.0)/100000d.0;

Lub

Math.round(selfEvaluate*100000d.0)*0.00000d1;

Jeśli potrzebujesz dużej liczby miejsc po przecinku, możesz użyć BigDecimal. W każdym razie {[2] } jest ważne. Bez niego zaokrąglenie 0. 33333d5 zwraca 0.33333 i tylko 9 cyfr jest dozwolone. Druga funkcja Bez .0 ma problemy z 0.30000 return 0.300000000000000000004.

 2
Author: Se Song,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-25 09:06:39

Aby to osiągnąć możemy użyć tego formatera:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

Lub:

DecimalFormat df = new DecimalFormat("0.00"); :

Użyj tej metody, aby uzyskać zawsze dwa miejsca po przecinku:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Definiowanie tych wartości:

91.32
5.22
11.5
1.2
2.6

Używając metody możemy uzyskać takie wyniki:

91.32
5.22
11.50
1.20
2.60

Demo online.

 2
Author: Jorgesys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 17:40:39

Pamiętaj, że ciąg.format() i DecimalFormat wytwarzają ciąg znaków przy użyciu domyślnych ustawień regionalnych. Mogą więc zapisywać sformatowaną liczbę z kropką lub przecinkiem jako separator między liczbą całkowitą i dziesiętną. Aby upewnić się, że zaokrąglony ciąg znaków jest w formacie, który chcesz użyć java.tekst.NumberFormat as so:

  Locale locale = Locale.ENGLISH;
  NumberFormat nf = NumberFormat.getNumberInstance(locale);
  // for trailing zeros:
  nf.setMinimumFractionDigits(2);
  // round to 2 digits:
  nf.setMaximumFractionDigits(2);

  System.out.println(nf.format(.99));
  System.out.println(nf.format(123.567));
  System.out.println(nf.format(123.0));

Będzie drukować w języku angielskim (bez względu na to, jakie jest twoje locale): 0.99 123.57 123.00

Przykład pochodzi z Farenda- Jak przekonwertować double NA String poprawnie .

 1
Author: pwojnowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-10 22:24:26

Gdzie dp = miejsce dziesiętne, które chcesz, i wartość jest Podwójna.

    double p = Math.pow(10d, dp);

    double result = Math.round(value * p)/p;
 0
Author: aim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-21 23:51:17

Jeśli weźmiemy pod uwagę 5 lub n liczby dziesiętnej. Może ta odpowiedź rozwiąże twój problem.

    double a = 123.00449;
    double roundOff1 = Math.round(a*10000)/10000.00;
    double roundOff2 = Math.round(roundOff1*1000)/1000.00;
    double roundOff = Math.round(roundOff2*100)/100.00;

    System.out.println("result:"+roundOff);

Wyjście będzie: 123.01
można to rozwiązać za pomocą funkcji pętlowej i rekurencyjnej.

 0
Author: Qamar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 07:36:21

Jeśli używasz technologii, która ma minimalne JDK. Oto sposób bez żadnych libów Javy:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
 0
Author: Craigo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-07 07:10:46

Ogólnie zaokrąglanie odbywa się przez skalowanie: round(num / p) * p

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the edge cases).
 */
double RoundCorrect(double num, int precision) {
    double c = 0.5 * EPSILON * num;
//  double p = Math.pow(10, precision); //slow
    double p = 1; while (precision--> 0) p *= 10;
    if (num < 0)
        p *= -1;
    return Math.round((num + c) * p) / p;
}

// testing edge cases
RoundCorrect(1.005, 2);   // 1.01 correct
RoundCorrect(2.175, 2);   // 2.18 correct
RoundCorrect(5.015, 2);   // 5.02 correct

RoundCorrect(-1.005, 2);  // -1.01 correct
RoundCorrect(-2.175, 2);  // -2.18 correct
RoundCorrect(-5.015, 2);  // -5.02 correct
 -1
Author: Amr Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-02 16:45:24