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.