Runda a Podwójna do 2 miejsc po przecinku [duplikat]

To pytanie ma już odpowiedź tutaj:

Jeśli wartość wynosi 200.3456, należy ją sformatować na 200.34. Jeśli jest 200, to powinno być 200.00.

Author: ryanyuyu, 2010-05-11

13 answers

Oto narzędzie, które zaokrągla (zamiast obcinając) podwójną do określonej liczby miejsc po przecinku.

Na przykład:

round(200.3456, 2); // returns 200.35

Wersja Oryginalna; uważaj z tym

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    long factor = (long) Math.pow(10, places);
    value = value * factor;
    long tmp = Math.round(value);
    return (double) tmp / factor;
}

To rozkłada się źle w przypadkach narożnych z bardzo dużą liczbą miejsc po przecinku (np. round(1000.0d, 17)) lub dużą liczbą całkowitą (np. round(90080070060.1d, 9)). Dzięki Sloinowi za zwrócenie na to uwagi.

Używam powyższego do zaokrąglania "nie-zbyt-duży" podwaja się do 2 lub 3 miejsc po przecinku szczęśliwie przez lata (na przykład, aby oczyścić czas w sekundach dla celów logowania: 27.987654321987 -> 27.99). Ale myślę, że najlepiej tego unikać, ponieważ bardziej niezawodne sposoby są łatwo dostępne, z czystszym kodem też.

Więc użyj tego zamiast

(zaadaptowane z tej odpowiedzi Louisa Wassermana i tej Sean Owen .)

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

Zauważ, że HALF_UP jest trybem zaokrąglania "powszechnie nauczanym w szkole". Peruse dokumentacja RoundingMode , jeśli podejrzewasz, że potrzebujesz czegoś innego, takiego jak zaokrąglenie .

Oczywiście, jeśli wolisz, możesz umieścić powyższe w jednej linii:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

I w każdym przypadku

Zawsze pamiętaj, że reprezentacje zmiennoprzecinkowe za pomocą float i doubleinexact. Na przykład rozważmy te wyrażenia:

999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001

Dla dokładności, chcesz użyć BigDecimal. I podczas gdy w to, użyj konstruktora, który bierze ciąg, nigdy ten, który bierze podwójnie. Na przykład, spróbuj wykonać to:

System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));

Kilka doskonałych dalszych lektur na ten temat:


If you wanted String formatowanie zamiast (lub dodatkowo do) ściśle zaokrąglanie liczb, zobacz inne odpowiedzi.

Zwróć szczególną uwagę, że round(200, 0) zwraca 200.0. Jeśli chcesz wydrukować "200.00", należy najpierw zaokrąglić, a następnie sformatować wynik dla wyjścia (co jest doskonale wyjaśnione w odpowiedź Jespera ).

 660
Author: Jonik,
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:34:59

Jeśli chcesz wydrukować double z dwoma cyframi po przecinku, użyj czegoś takiego:

double value = 200.3456;
System.out.printf("Value: %.2f", value);

Jeśli chcesz mieć wynik w String zamiast być drukowanym na konsoli, użyj String.format() z tymi samymi argumentami:

String result = String.format("%.2f", value);

Lub użyj klasy DecimalFormat:

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
 271
Author: Jesper,
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
2010-05-11 07:04:30

Myślę, że tak jest łatwiej:

double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(time));

System.out.println(time); // 200.35

Zauważ, że to rzeczywiście będzie zaokrąglanie za Ciebie, a nie tylko formatowanie.

 105
Author: Santiago,
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
2013-07-16 00:28:59

Najłatwiej byłoby zrobić taki trik;

double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;

Jeśli val zaczyna się od 200.3456, to idzie do 20034.56, a następnie zaokrągla się do 20035, a następnie dzielimy go na 200.34.

Jeśli chcesz zawsze zaokrąglać w dół, zawsze możemy obciąć, rzucając do int:

double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;

Ta technika będzie działać w większości przypadków, ponieważ dla bardzo dużych podwójnych (dodatnich lub ujemnych) może przepełnić. ale jeśli wiesz, że twoje wartości będą w odpowiednim zakresie, to powinno działać dla Ciebie.

 55
Author: luke,
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-02-08 14:48:08

Proszę użyć Apache commons math :

Precision.round(10.4567, 2)
 42
Author: Pritesh Mhatre,
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-08-15 14:46:04
function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

Zwróć uwagę na ToString ()!!!!

To dlatego, że BigDecimal konwertuje dokładną binarną formę sobowtóra!!!

Są to różne sugerowane metody i ich przypadki niepowodzenia.

// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue() 

Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val) 
// By default use half even, works if you change mode to half_up 

Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
 25
Author: Luca Vix,
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-07-19 22:48:33
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));
 16
Author: Abdullah AlHazmy,
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-12 13:13:30

Jeśli naprawdę chcesz to samo podwójne, ale zaokrąglone w sposób, w jaki chcesz, możesz użyć BigDecimal, na przykład

new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
 14
Author: daoway,
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-10-24 18:10:51
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
 14
Author: user1692711,
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
2013-11-18 12:18:40

Zaokrąglanie sobowtóra zazwyczaj nie jest tym, czego się chce. Zamiast tego użyj String.format() reprezentowanie go w pożądanym formacie.

 8
Author: Ignacio Vazquez-Abrams,
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
2010-05-11 06:38:54

Dla dwóch zaokrąglonych cyfr. Bardzo proste i w zasadzie aktualizujesz zmienną, a nie tylko wyświetlasz cele, które robi DecimalFormat.

x = Math.floor(x * 100) / 100;

 5
Author: Srujan Kumar Gulla,
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-10-18 19:59:12
value = (int)(value * 100 + 0.5) / 100.0;
 0
Author: user2068610,
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
2013-02-13 14:19:50

W twoim pytaniu, wydaje się, że chcesz uniknąć zaokrąglania liczb, jak również? Tak myślę .format() będzie zaokrąglać liczby za pomocą half-up, afaik?
więc jeśli chcesz zaokrąglać, 200.3456 powinno być 200.35 dla dokładności 2. ale w Twoim przypadku, jeśli chcesz tylko pierwsze 2, a następnie odrzucić resztę?

Można go pomnożyć przez 100, a następnie rzucić do int (lub biorąc głos liczby), przed podzieleniem przez 100 ponownie.

200.3456 * 100 = 20034.56;  
(int) 20034.56 = 20034;  
20034/100.0 = 200.34;

Możesz mieć problemy z naprawdę naprawdę dużym liczby zbliżone do granicy. W takim przypadku konwersja na łańcuch i podłańcuch działa równie łatwo.

 0
Author: bryanallott,
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-08-09 18:54:14