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

.

seba123neo
źródło

Odpowiedzi:

561

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

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

Dokumentacja

Arve
źródło
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

Nick Campion
źródło
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

Anupam
źródło
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));
FBB
źródło
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.

Tony L.
źródło
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

Robin Davies
źródło
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();
    }
M. Usman Khan
źródło
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;
}
Ethan Johnson
źródło
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ś.

n3utrino
źródło
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));
}
Blogger
źródło