Sformatuj zmiennoprzecinkowe do n miejsc dziesiętnych


220

Muszę sformatować liczbę zmiennoprzecinkową do „n” miejsc dziesiętnych.

próbował BigDecimal, ale zwracana wartość jest nieprawidłowa ...

public static float Redondear(float pNumero, int pCantidadDecimales) {
    // the function is call with the values Redondear(625.3f, 2)
    BigDecimal value = new BigDecimal(pNumero);
    value = value.setScale(pCantidadDecimales, RoundingMode.HALF_EVEN); // here the value is correct (625.30)
    return value.floatValue(); // but here the values is 625.3
}

Muszę zwrócić wartość zmiennoprzecinkową z określoną przeze mnie liczbą miejsc dziesiętnych.

Potrzebuję Floatzwrotu wartości nieDouble

.

Odpowiedzi:


561

Możesz również przekazać wartość zmiennoprzecinkową i użyć:

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

Dokumentacja


70
Zachowaj ostrożność, ponieważ format String.format zależy od bieżącej konfiguracji lokalnej, możesz nie otrzymać kropki jako separatora. Wolę używaćString.format(java.util.Locale.US,"%.2f", floatValue);
Gomino

6
ta odpowiedź daje wartość String, a nie Float, nie uważam, że to dobra odpowiedź.
ZhaoGang,

3
Dlaczego wymuszasz kropkę jako separator?
Mark Buikema

1
@MarkBuikema Myślę, że istnieją przypadki, w których byłoby to absolutnie konieczne, na przykład podczas kompilacji formatów dokumentów opartych na standardach, np. Dokumenty PDF.
Tjaart,

39

Spójrz na DecimalFormat . Możesz go łatwo użyć do pobrania liczby i podania określonej liczby miejsc po przecinku.

Edycja : przykład


1
+1. Oto dokumentacja dla Androida , która powinna być zasadniczo taka sama.
Zach L

ale potrzebuję, aby wynik był liczbą zmiennoprzecinkową, a nie ciągiem.
seba123neo

Mówisz, że chcesz zaokrąglić pływak? Zwykle jedyną precyzją czasu pływaka jest wyświetlenie.
Nick Campion

przepraszam, masz rację, byłem zdezorientowany, po prostu sformatuj numer, gdy jest wyświetlany na ekranie, nie wcześniej, to było moje pytanie, dziękuję bardzo, problem rozwiązany.
seba123neo

Warto zauważyć, że DecimalFormatodradza się używanie konstruktora, zobacz moją odpowiedź na poprawne użycie NumberFormat.
FBB,

17

Spróbuj, to bardzo mi pomogło

BigDecimal roundfinalPrice = new BigDecimal(5652.25622f).setScale(2,BigDecimal.ROUND_HALF_UP);

Wynik będzie zaokrąglonyCena -> 5652,26


2
Jest to bardziej przydatne dla tych, którzy chcą zaokrąglić i wykonać z nim dalsze obliczenia, w przeciwnym razie odpowiedź Arve jest prawdopodobnie najlepsza.
Gerard

Działa to również z GWT. String.format () - nie ma.
AlexV

15

Warto zauważyć, że DecimalFormatodradza się używanie konstruktora. Jawadok dla tej klasy stwierdza:

Na ogół nie należy wywoływać konstruktorów DecimalFormat bezpośrednio, ponieważ metody fabryczne NumberFormat mogą zwracać podklasy inne niż DecimalFormat.

https://docs.oracle.com/javase/8/docs/api/java/text/DecimalFormat.html

Musisz więc (na przykład):

NumberFormat formatter = NumberFormat.getInstance(Locale.US);
formatter.setMaximumFractionDigits(2);
formatter.setMinimumFractionDigits(2);
formatter.setRoundingMode(RoundingMode.HALF_UP); 
Float formatedFloat = new Float(formatter.format(floatValue));

To nie działa, gdy (na przykład) floatValue = 8.499. Daje 8.5.
Shiva krishna Chippa

3
@ShivakrishnaChippa: tak, ponieważ tutaj określamy, że po przecinku chcemy 2 cyfry i zaokrąglić w górę. W takim przypadku 8,499 jest zaokrąglane do 8,5. Jeśli chcesz wyświetlać 8.499, po prostu ustaw 3 jako cyfry maksymalnego ułamka.
FBB,

6

Oto krótka próbka z wykorzystaniem DecimalFormatklasy wymienionej przez Nicka.

float f = 12.345f;
DecimalFormat df = new DecimalFormat("#.00");
System.out.println(df.format(f));

Dane wyjściowe instrukcji print będą wynosić 12,35. Zauważ, że zaokrągli to dla ciebie.


Warto zauważyć, że DecimalFormatodradza się używanie konstruktora, zobacz moją odpowiedź na poprawne użycie NumberFormat.
FBB,

5

Trochę zaskoczyło, że nikt nie wskazał bezpośredniego sposobu, aby to zrobić, co jest dość łatwe.

double roundToDecimalPlaces(double value, int decimalPlaces)
{
      double shift = Math.pow(10,decimalPlaces);
      return Math.round(value*shift)/shift;
}

Z pewnością nie robi to jednak półokrągłego zaokrąglenia.

Jeśli chodzi o to, co warto, półokrągłe zaokrąglenie będzie chaotyczne i nieprzewidywalne za każdym razem, gdy zmieszasz binarne wartości zmiennoprzecinkowe z arytmetyką 10. Jestem prawie pewien, że nie da się tego zrobić. Podstawowym problemem jest to, że wartości takiej jak 1.105 nie można dokładnie przedstawić w liczbach zmiennoprzecinkowych. Wartość zmiennoprzecinkowa będzie miała postać 1.105000000000001 lub 1.10499999999999999. Tak więc każda próba wykonania półokrągłego zaokrąglenia idzie w górę z powodu reprezentatywnych błędów kodowania.

Implementacje zmiennoprzecinkowe IEEE wykonują półokrągłe, ale robią binarne półokrągłe, a nie dziesiętne półokrągłe. Więc prawdopodobnie nic ci nie jest


Od jakiegoś czasu korzystam z tej metody, ale uważam, że powjest to zbyt kosztowna operacja do zaokrąglania?
Xerus

Nigdy nie optymalizuj, dopóki nie masz problemów z wydajnością. Ważniejsze jest, aby mieć rację niż szybko. I nie mogę szczerze wyobrazić sobie aplikacji, w której wydajność kontrolowanego zaokrąglania byłaby problemem, chyba że byłbyś Visa lub Mastercard (który po prostu rzuciłby w to więcej maszyn). Pow () jest prawdopodobnie szybszy niż round ().
Robin Davies,

2
public static double roundToDouble(float d, int decimalPlace) {
        BigDecimal bd = new BigDecimal(Float.toString(d));
        bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
        return bd.doubleValue();
    }

2

Jest to znacznie mniej profesjonalny i znacznie droższy sposób, ale powinien być łatwiejszy do zrozumienia i bardziej pomocny dla początkujących.

public static float roundFloat(float F, int roundTo){

    String num = "#########.";

    for (int count = 0; count < roundTo; count++){
        num += "0";
    }

    DecimalFormat df = new DecimalFormat(num);

    df.setRoundingMode(RoundingMode.HALF_UP);

    String S = df.format(F);
    F = Float.parseFloat(S);

    return F;
}

1

Myślę, że chcesz

return value.toString();

i użyj wartości zwracanej do wyświetlenia.

value.floatValue();

zawsze zwróci 625,3, ponieważ jest głównie używany do obliczania czegoś.


ale potrzebuję, aby wynik był liczbą zmiennoprzecinkową, a nie ciągiem.
seba123neo

2
jeśli potrzebujesz pływaka, aby pokazać go użytkownikowi, może być coś nie tak z projektem aplikacji. Zwykle liczba zmiennoprzecinkowa jest używana do obliczania, a ciąg znaków służy do pokazywania jej użytkownikowi.
n3utrino,

przepraszam, masz rację, byłem zdezorientowany, po prostu sformatuj numer, gdy jest wyświetlany na ekranie, nie wcześniej, to było moje pytanie, dziękuję bardzo, problem rozwiązany.
seba123neo

1

Szukałem odpowiedzi na to pytanie, a później opracowałem metodę! :) Sprawiedliwe ostrzeżenie, zaokrągla wartość.

private float limitDigits(float number) {
    return Float.valueOf(String.format(Locale.getDefault(), "%.2f", number));
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.