Jak skrócić podwójne do dwóch miejsc po przecinku w Javie?

98

Na przykład mam zmienną 3.545555555, którą chciałbym skrócić do zaledwie 3,54.

Jasio
źródło
21
To NIE jest duplikat. Obcinanie i zaokrąglanie to dwie zupełnie różne rzeczy.
markthegrea
Zgoda, nie wiem, dlaczego jest to oznaczone jako duplikat.
Bassinator,

Odpowiedzi:

147

Jeśli chcesz to do celów wyświetlania, użyj java.text.DecimalFormat:

 new DecimalFormat("#.##").format(dblVar);

Jeśli potrzebujesz go do obliczeń, użyj java.lang.Math:

 Math.floor(value * 100) / 100;
Bozho
źródło
50
To nie wyświetli obciętego 3,545555555 do 3,54, ale zaokrąglonego do 3,55. DecimalFormat.setRoundingMode () należy ustawić na RoundingMode.FLOOR;
Christian García
9
to nie działa dla mnie Math.floor (9,62 * 100) / 100 daje 9,61
Mani
4
Użycie floordo obcinania działa tylko w przypadku wartości dodatnich.
Dev
4
@ ChristianGarcía Obcinanie odbywa się prawidłowo, RoundingMode.DOWNjak RoudingMode.FLOORzawsze zaokrągla w kierunku ujemnej nieskończoności.
Dev
46
DecimalFormat df = new DecimalFormat(fmt);
df.setRoundingMode(RoundingMode.DOWN);
s = df.format(d);

Sprawdź dostępne RoundingModei DecimalFormat.

Cedric Dubourg
źródło
Nie dotyczy pytania, w którym prosiło się raczej o obcięcie niż zaokrąglenie.
Basil Bourque,
8
@BasilBourque RoundingMode.DOWN to obcięcie. Porównaj z innymi odpowiedziami, które błędnie zalecają funkcje podłogi (podłoga obcina tylko liczby dodatnie), działa to poprawnie zarówno dla wartości dodatnich, jak i ujemnych.
Dev
1
@Dev stoję poprawione. Teraz widzę, że DOWNrzeczywiście ma to wpływ na obcięcie liczb dodatnich i ujemnych. Jak widać w tabeli przykładów w dok .
Basil Bourque
25

Bit Old Forum, Żadna z powyższych odpowiedzi nie działała zarówno dla wartości dodatnich, jak i ujemnych (mam na myśli obliczenia i po prostu obcinanie bez zaokrąglania). Z linku Jak zaokrąglić liczbę do n miejsc dziesiętnych w języku Java

private static BigDecimal truncateDecimal(double x,int numberofDecimals)
{
    if ( x > 0) {
        return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_FLOOR);
    } else {
        return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_CEILING);
    }
}

Ta metoda działała dobrze dla mnie.

System.out.println(truncateDecimal(0, 2));
    System.out.println(truncateDecimal(9.62, 2));
    System.out.println(truncateDecimal(9.621, 2));
    System.out.println(truncateDecimal(9.629, 2));
    System.out.println(truncateDecimal(9.625, 2));
    System.out.println(truncateDecimal(9.999, 2));
    System.out.println(truncateDecimal(-9.999, 2));
    System.out.println(truncateDecimal(-9.0, 2));

Wyniki:

0.00
9.62
9.62
9.62
9.62
9.99
-9.99
-9.00
Mani
źródło
to jest odpowiedź, która jest bardziej skalowalna dla większej liczby przypadków testowych
diego matos - keke
return new BigDecimal (x) .setScale (numberofDecimals, RoundingMode.DOWN) .doubleValue ();
Shimon Doodkin
wydaje się zaokrąglony w dół, tak jak miałeś na myśli: docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html
Shimon Doodkin
9

Zauważ najpierw, że a doublejest ułamkiem binarnym i tak naprawdę nie ma miejsc dziesiętnych.

Jeśli potrzebujesz miejsc dziesiętnych, użyj a BigDecimal, który ma setScale()metodę obcinania, lub użyj, DecimalFormataby uzyskać String.

Michael Borgwardt
źródło
7

Jeśli z jakiegoś powodu nie chcesz użyć a BigDecimal, możesz rzucić doublena an, intaby go skrócić.

Jeśli chcesz skrócić do miejsca Ones :

  • po prostu rzuć na int

Na dziesiąte miejsce:

  • pomnóż przez dziesięć
  • rzut do int
  • odrzucić z powrotem do double
  • i podziel przez dziesięć.

Setki miejsc

  • pomnóż i podziel przez 100 itd.

Przykład:

static double truncateTo( double unroundedNumber, int decimalPlaces ){
    int truncatedNumberInt = (int)( unroundedNumber * Math.pow( 10, decimalPlaces ) );
    double truncatedNumber = (double)( truncatedNumberInt / Math.pow( 10, decimalPlaces ) );
    return truncatedNumber;
}

W tym przykładzie decimalPlacesbyłaby to liczba ostatnich miejsc, do których chcesz się udać, więc 1 zaokrągliłoby do dziesiątych miejsc, 2 do setnych itd. (0 zaokrągliło do jedności , a ujemne jedno do dziesiątek itp.)

Tarvis
źródło
3
To straszne ogólne rozwiązanie. Zarówno mnożenie, jak i rzutowanie kończą się wyrzuceniem danych i skutkiem tego, co jest faktycznie liczbami losowymi, jeśli unroundedNumberjest wystarczająco duże. Może działać na przykład w pytaniu, ale ogólne rozwiązanie powinno działać w przypadku każdego double.
blm
6

Wydaje mi się, że sformatowanie jako ciąg i zamiana z powrotem na podwójne da pożądany wynik.

Podwójna wartość nie będzie round (), floor () ani ceil ().

Szybkim rozwiązaniem może być:

 String sValue = (String) String.format("%.2f", oldValue);
 Double newValue = Double.parseDouble(sValue);

Możesz użyć sValue do celów wyświetlania lub newValue do obliczeń.

Jao Assy
źródło
1
Zaokrągla mnie do najbliższej wartości. Na przykład: 0,018 jest zamieniane na 0,02, kiedy to zrobiłem.
karan patel
3

Może Math.floor(value * 100) / 100? Pamiętaj, że wartości takie jak 3.54mogą nie być dokładnie reprezentowane przez rozszerzenie double.

Vlad
źródło
3

Możesz użyć obiektu NumberFormat Class do wykonania zadania.

// Creating number format object to set 2 places after decimal point
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);            
nf.setGroupingUsed(false);

System.out.println(nf.format(precision));// Assuming precision is a double type variable
Rushdi Shams
źródło
3

3.545555555, aby uzyskać 3.54. Spróbuj tego:

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

    df.setRoundingMode(RoundingMode.FLOOR);

    double result = new Double(df.format(3.545555555);

To da = 3,54!

Ankush G.
źródło
Ale dostanę 3,5, jeśli ustawię tę wartość na 3,50123
Cyrus
1

Oto metoda, której używam:

double a=3.545555555; // just assigning your decimal to a variable
a=a*100;              // this sets a to 354.555555
a=Math.floor(a);      // this sets a to 354
a=a/100;              // this sets a to 3.54 and thus removing all your 5's

Można to również zrobić:

a=Math.floor(a*100) / 100;
Mitchell Hynes
źródło
0

Może po:

double roundTwoDecimals(double d) { 
      DecimalFormat twoDForm = new DecimalFormat("#.##"); 
      return Double.valueOf(twoDForm.format(d));
}  
Ritesh Mengji
źródło
Zobacz inne odpowiedzi. Nie możesz tego zrobić niezawodnie, jeśli odpowiedź ma być przedstawiona w postaci zmiennoprzecinkowej.
Markiz Lorne
0

Szybkim sprawdzeniem jest użycie metody Math.floor. Utworzyłem poniżej metodę sprawdzania podwójnego dla dwóch lub mniej miejsc po przecinku:

public boolean checkTwoDecimalPlaces(double valueToCheck) {

    // Get two decimal value of input valueToCheck 
    double twoDecimalValue = Math.floor(valueToCheck * 100) / 100;

    // Return true if the twoDecimalValue is the same as valueToCheck else return false
    return twoDecimalValue == valueToCheck;
}
chris31389
źródło
-1

Mam nieco zmodyfikowaną wersję Mani .

private static BigDecimal truncateDecimal(final double x, final int numberofDecimals) {
    return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_DOWN);
}

public static void main(String[] args) {
    System.out.println(truncateDecimal(0, 2));
    System.out.println(truncateDecimal(9.62, 2));
    System.out.println(truncateDecimal(9.621, 2));
    System.out.println(truncateDecimal(9.629, 2));
    System.out.println(truncateDecimal(9.625, 2));
    System.out.println(truncateDecimal(9.999, 2));
    System.out.println(truncateDecimal(3.545555555, 2));

    System.out.println(truncateDecimal(9.0, 2));
    System.out.println(truncateDecimal(-9.62, 2));
    System.out.println(truncateDecimal(-9.621, 2));
    System.out.println(truncateDecimal(-9.629, 2));
    System.out.println(truncateDecimal(-9.625, 2));
    System.out.println(truncateDecimal(-9.999, 2));
    System.out.println(truncateDecimal(-9.0, 2));
    System.out.println(truncateDecimal(-3.545555555, 2));

}

Wynik:

0.00
9.62
9.62
9.62
9.62
9.99
9.00
3.54
-9.62
-9.62
-9.62
-9.62
-9.99
-9.00
-3.54
HolyLance
źródło
-2

To zadziałało dla mnie:

double input = 104.8695412  //For example

long roundedInt = Math.round(input * 100);
double result = (double) roundedInt/100;

//result == 104.87

Osobiście podoba mi się ta wersja, ponieważ w rzeczywistości wykonuje zaokrąglanie liczbowo, zamiast konwertować ją na łańcuch (lub podobny), a następnie formatować.

Rainbow975
źródło
1
Pierwotne pytanie dotyczy obcięcia, a nie zaokrąglenia. Ponadto zamiana podwójnej na długą nie będzie działać dobrze, jeśli podwójna jest wystarczająco duża.
blm
-2
//if double_v is 3.545555555
String string_v= String.valueOf(double_v);
int pointer_pos = average.indexOf('.');//we find the position of '.'
string_v.substring(0, pointer_pos+2));// in this way we get the double with only 2 decimal in string form
double_v = Double.valueOf(string_v);//well this is the final result

cóż, może to być trochę niezręczne, ale myślę, że może rozwiązać twój problem :)

user5251903
źródło
Ten kod wykonuje swoje zadanie, ale nie jest elegancki i ma słabą wydajność. Może to być w porządku w projektach szkolnych, ale zdecydowanie nie jest rozwiązaniem, którego ktoś użyłby w produkcji dla dowolnego systemu, chyba że później będziesz mieć ból głowy.
cbaldan