Jak zaokrąglać liczbę do n miejsc po przecinku w Javie
To, co chciałbym, to metoda konwersji podwójnego na ciąg, który zaokrągla się metodą half-up - tzn. jeśli liczba dziesiętna, która ma być zaokrąglona, wynosi 5, zawsze zaokrągla się do poprzedniej liczby. Jest to standardowa metoda zaokrąglania, której większość ludzi oczekuje w większości sytuacji.
Chciałbym również, aby wyświetlane były tylko znaczące cyfry - tzn. nie powinno być żadnych końcowych zer.
Wiem, że jedną z metod jest użycie String.format
"metoda": {]}
String.format("%.5g%n", 0.912385);
Zwraca:
0.91239
Co jest świetne, jednak zawsze wyświetla liczby z 5 miejscami po przecinku, nawet jeśli nie są znaczące:
String.format("%.5g%n", 0.912300);
Zwraca:
0.91230
Inną metodą jest użycie DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
Zwraca:
0.91238
Jednak, jak widać, używa pół-parzystego zaokrąglenia. Oznacza to, że zaokrągli się w dół, jeśli poprzednia cyfra jest parzysta. Ja bym chciał:
0.912385 -> 0.91239
0.912300 -> 0.9123
Jaki jest najlepszy sposób na osiągnięcie tego w Javie?
29 answers
Użycie setRoundingMode
, set the RoundingMode
jawnie, aby rozwiązać problem z half-even round, następnie użyj wzorca formatu dla wymaganego wyjścia.
Przykład:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
Daje wyjście:
12
123.1235
0.23
0.1
2341234.2125
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-07-03 13:10:53
Zakładając, że value
jest double
, możesz zrobić:
(double)Math.round(value * 100000d) / 100000d
To 5 cyfr precyzji. Liczba zer oznacza liczbę miejsc po przecinku.
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-09-16 12:17:03
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
Da ci BigDecimal
. Aby uzyskać ciąg znaków, po prostu wywołaj tę metodę BigDecimal
toString
lub metodę toPlainString
dla Java 5+ dla zwykłego ciągu znaków.
Przykładowy program:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
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-03-01 08:00:31
Możesz również użyć
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
Aby upewnić się, że masz trailing 0 ' s.
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
2008-09-30 16:58:12
Jak zauważyli inni, poprawną odpowiedzią jest użycie DecimalFormat
lub BigDecimal
. Zmiennoprzecinkowy nie ma miejsc po przecinku, więc nie można zaokrąglić/obciąć do określonej liczby z nich w pierwszej kolejności. Musisz pracować w radix dziesiętny, i to jest to, co te dwie klasy zrobić.
Zamieszczam poniższy kod jako kontr-przykład do wszystkich odpowiedzi w tym wątku i rzeczywiście w całym StackOverflow (i gdzie indziej), które zalecają mnożenie, a następnie okrojenie, po którym następuje podział. Zwolennicy tej techniki powinni wyjaśnić, dlaczego poniższy kod generuje błędne dane wyjściowe w ponad 92% przypadków.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Wyjście tego programu:
10001 trials 9251 errors
EDIT: aby odnieść się do niektórych komentarzy poniżej przerobiłem część modułu pętli testowej używając BigDecimal
i new MathContext(16)
dla operacji modułu w następujący sposób:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Wynik:
10001 trials 4401 errors
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-12-18 03:53:47
Załóżmy, że masz
double d = 9232.129394d;
Możesz użyć BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
Lub bez BigDecimal
d = Math.round(d*100)/100.0d;
Z obu rozwiązań d == 9232.13
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-09-14 22:30:33
Możesz użyć klasy DecimalFormat.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
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
2011-09-29 07:01:59
Real ' S Java How-To posts To rozwiązanie, które jest również kompatybilne z wersjami przed Javą 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
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
2009-09-01 11:14:32
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
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
2008-09-30 16:09:26
@Milhous: format dziesiętny dla zaokrąglania jest doskonały:
[[8]} dodam, że metoda ta jest bardzo dobra w dostarczaniu rzeczywistego numeryczny mechanizm zaokrąglania-nie tylko wizualnie, ale także podczas przetwarzania.Możesz również użyć
DecimalFormat df = new DecimalFormat("#.00000"); df.format(0.912385);
Aby upewnić się, że masz trailing 0 ' s.
Hipotetycznie: musisz zaimplementować mechanizm zaokrąglania do GUI program. Aby zmienić dokładność / precyzję wyniku po prostu zmień format karetki (tj. w nawiasach). Tak że:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
Zwróci jako wyjście: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
Zwróci jako wyjście: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
Zwróci jako wyjście: 0.9124
[EDIT: również jeśli format karetki jest taki ("#0.###########") I ty
3.1415926, dla argumentu, DecimalFormat
nie generuje żadnych śmieci (np. końcowe zera) i zwróci:
3.1415926
.. jeśli jesteś taka skłonna. Przyznaję, to trochę gadatliwe.
dla upodobania niektórych dev ' ów - ale ma małą pamięć.
podczas przetwarzania i jest bardzo łatwy do wdrożenia.]
Więc zasadniczo, piękno DecimalFormat jest to, że jednocześnie obsługuje ciąg wygląd - jak również poziom precyzji zaokrąglania ustawiony. Ergo: ty uzyskaj dwie korzyści w cenie jednej implementacji kodu. ;)
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
2011-07-03 19:55:34
Możesz użyć następującej metody użytkowej -
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
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
2011-04-27 15:56:25
Oto podsumowanie tego, czego możesz użyć, jeśli chcesz, aby wynik był ciągiem znaków:
-
DecimalFormat df = new DecimalFormat("#.#####"); df.setRoundingMode(RoundingMode.HALF_UP); String str1 = df.format(0.912385)); // 0.91239
-
String str2 = new BigDecimal(0.912385) .setScale(5, BigDecimal.ROUND_HALF_UP) .toString();
Oto sugestia, jakich bibliotek możesz użyć, jeśli chcesz double
w rezultacie. Nie polecałbym go jednak do konwersji łańcuchów, ponieważ double może nie być w stanie dokładnie reprezentować tego, co chcesz (patrz np. tutaj):
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:02:47
Zwięzłe rozwiązanie:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) Math.round(value * scale) / scale;
}
Zobacz też: https://stackoverflow.com/a/22186845/212950 Podziękowania dla jpdymond za zaoferowanie tego.
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-07-26 14:41:08
Możesz użyć BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Zobacz: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
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
2014-07-22 09:49:35
Spróbuj tego: org.Apacz.commons.math3.util.Precyzja.round (double x, int scale)
Zobacz: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html
Wewnętrzna implementacja tej metody to:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
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
2014-02-20 05:04:07
Ponieważ nie znalazłem pełnej odpowiedzi na ten temat, ułożyłem klasę, która powinna sobie z tym poradzić poprawnie, z obsługą dla:
- formatowanie : łatwo formatować podwójny ciąg znaków z określoną liczbą miejsc po przecinku
- Parsing : parsuje sformatowaną wartość z powrotem do podwójnego
- Locale : Formatuj i analizuj używając domyślnego locale
- notacja wykładnicza : zacznij używać notacji wykładniczej po pewnym próg
Użycie jest dość proste :
(dla tego przykładu używam niestandardowych ustawień regionalnych)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Oto klasa :
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
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-11-11 22:39:16
Na wypadek, gdyby ktoś jeszcze potrzebował pomocy. To rozwiązanie sprawdza się u mnie doskonale.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
Zwraca {[1] } z żądanym wyjściem.
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-03-03 11:43:00
Jeśli naprawdę chcesz liczby dziesiętne do obliczeń (i nie tylko dla danych wyjściowych), nie używaj binarnego formatu zmiennoprzecinkowego, takiego jak double.
Use BigDecimal or any other decimal-based format.
Używam BigDecimal do obliczeń, ale pamiętaj, że zależy to od wielkości liczby, z którymi masz do czynienia. W większości moich implementacji znajduję parsowanie z podwójnego lub liczba całkowita do Long wystarcza do bardzo dużych obliczeń liczbowych.
In fact, I ' ve ostatnio używane parsed-to-Long, aby uzyskać dokładne reprezentacje (w przeciwieństwie do wyników hex) w GUI dla liczb tak dużych jak ################################# postacie (jako przykład).
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-05-30 18:33:04
Jeśli używasz DecimalFormat
do konwersji double
na String
, jest to bardzo proste:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
Istnieje kilka wartości RoundingMode
do wyboru, w zależności od wymaganego zachowania.
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-28 11:54:36
Poniższy fragment kodu pokazuje, jak wyświetlić n cyfr. Sztuczka polega na ustawieniu zmiennej pp na 1, po której następuje N zer. W poniższym przykładzie zmienna pp value ma 5 zer, więc wyświetlone zostanie 5 cyfr.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
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-11-12 13:09:52
Przyszedłem tu po prostą odpowiedź, jak zaokrąglić liczbę. Jest to odpowiedź uzupełniająca, aby to zapewnić.
Jak zaokrąglać liczbę w Javie
Najczęstszym przypadkiem jest użycie Math.round()
.
Math.round(3.7) // 4
Liczby są zaokrąglane do najbliższej liczby całkowitej. Wartość .5
jest zaokrąglana w górę. Jeśli potrzebujesz innego zachowania zaokrąglania niż to, możesz użyć jednej z innych funkcji Math . Zobacz porównanie poniżej.
Runda
Jako podane powyżej, to zaokrągla się do najbliższej liczby całkowitej. .5
liczby dziesiętne zaokrąglają się. Ta metoda zwraca int
.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
Ceil
Każda wartość dziesiętna jest zaokrąglana do następnej liczby całkowitej. To idzie do ceil ing. Metoda ta zwraca double
.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
Podłoga
Każda wartość dziesiętna jest zaokrąglana w dół do następnej liczby całkowitej. Metoda ta zwraca double
.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
Rint
To jest podobne do rundy w tym wartości dziesiętne zaokrąglają się do najbliższej liczby całkowitej. Jednak w przeciwieństwie do round
, .5
wartości zaokrąglają się do parzystej liczby całkowitej. Metoda ta zwraca double
.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
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-02-20 14:42:47
Zgadzam się z wybraną odpowiedzią na użycie DecimalFormat
- - - lub alternatywnie BigDecimal
.
Przeczytaj najpierw Update poniżej!
Jeśli jednak zrobisz chcesz zaokrąglać podwójną wartość i uzyskać wynik double
, możesz użyć org.apache.commons.math3.util.Precision.round(..)
, Jak wspomniano powyżej. Implementacja używa BigDecimal
, jest powolna i tworzy śmieci.
Podobna, ale szybka i pozbawiona śmieci metoda jest dostarczana przez narzędzie DoubleRounder
w bibliotece decimal4j:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Will wyjście
0.667
0.666
1000.0
9.00800700601E10
Zobacz https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Zrzeczenie się: jestem zaangażowany w projekt decimal4j.
Aktualizacja:
Jak zauważył @iaforek, DoubleRounder czasami zwraca sprzeczne wyniki. Powodem jest to, że wykonuje matematycznie poprawne zaokrąglanie. Na przykład DoubleRounder.round(256.025d, 2)
zostanie zaokrąglone w dół do 256.02, ponieważ Podwójna wartość reprezentowana jako 256.025 d jest nieco mniejsza niż wartość racjonalna 256.025 i w związku z tym zostanie zaokrąglona w dół.
Uwagi:
- to zachowanie jest bardzo podobne do konstruktora
BigDecimal(double)
(ale nie dovalueOf(double)
, który używa konstruktora łańcuchowego).
Problem można obejść za pomocą podwójnego zaokrąglenia do większej precyzji, ale jest to skomplikowane i nie będę tu wchodzić w szczegóły]}
Z tych powodów i wszystkich wymienionych powyżej w tym poście nie mogę polecić aby użyć DoubleRounder .
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-06-11 23:42:35
DecimalFormat jest najlepszym sposobem na wyjście, ale nie wolę go. Zawsze robię to cały czas, ponieważ Zwraca podwójną wartość. Więc mogę użyć go więcej niż tylko wyjście.
Math.round(selfEvaluate*100000d.0)/100000d.0;
Lub
Math.round(selfEvaluate*100000d.0)*0.00000d1;
Jeśli potrzebujesz dużej liczby miejsc po przecinku, możesz użyć BigDecimal. W każdym razie {[2] } jest ważne. Bez niego zaokrąglenie 0. 33333d5 zwraca 0.33333 i tylko 9 cyfr jest dozwolone. Druga funkcja Bez .0
ma problemy z 0.30000 return 0.300000000000000000004.
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-11-25 09:06:39
Aby to osiągnąć możemy użyć tego formatera:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
Lub:
DecimalFormat df = new DecimalFormat("0.00"); :
Użyj tej metody, aby uzyskać zawsze dwa miejsca po przecinku:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Definiowanie tych wartości:
91.32
5.22
11.5
1.2
2.6
Używając metody możemy uzyskać takie wyniki:
91.32
5.22
11.50
1.20
2.60
Demo online.
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-03-14 17:40:39
Pamiętaj, że ciąg.format() i DecimalFormat wytwarzają ciąg znaków przy użyciu domyślnych ustawień regionalnych. Mogą więc zapisywać sformatowaną liczbę z kropką lub przecinkiem jako separator między liczbą całkowitą i dziesiętną. Aby upewnić się, że zaokrąglony ciąg znaków jest w formacie, który chcesz użyć java.tekst.NumberFormat as so:
Locale locale = Locale.ENGLISH;
NumberFormat nf = NumberFormat.getNumberInstance(locale);
// for trailing zeros:
nf.setMinimumFractionDigits(2);
// round to 2 digits:
nf.setMaximumFractionDigits(2);
System.out.println(nf.format(.99));
System.out.println(nf.format(123.567));
System.out.println(nf.format(123.0));
Będzie drukować w języku angielskim (bez względu na to, jakie jest twoje locale): 0.99 123.57 123.00
Przykład pochodzi z Farenda- Jak przekonwertować double NA String poprawnie .
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-11-10 22:24:26
Gdzie dp = miejsce dziesiętne, które chcesz, i wartość jest Podwójna.
double p = Math.pow(10d, dp);
double result = Math.round(value * p)/p;
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
2014-04-21 23:51:17
Jeśli weźmiemy pod uwagę 5 lub n liczby dziesiętnej. Może ta odpowiedź rozwiąże twój problem.
double a = 123.00449;
double roundOff1 = Math.round(a*10000)/10000.00;
double roundOff2 = Math.round(roundOff1*1000)/1000.00;
double roundOff = Math.round(roundOff2*100)/100.00;
System.out.println("result:"+roundOff);
Wyjście będzie: 123.01
można to rozwiązać za pomocą funkcji pętlowej i rekurencyjnej.
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-11-22 07:36:21
Jeśli używasz technologii, która ma minimalne JDK. Oto sposób bez żadnych libów Javy:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
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-01-07 07:10:46
Ogólnie zaokrąglanie odbywa się przez skalowanie: round(num / p) * p
/**
* MidpointRounding away from zero ('arithmetic' rounding)
* Uses a half-epsilon for correction. (This offsets IEEE-754
* half-to-even rounding that was applied at the edge cases).
*/
double RoundCorrect(double num, int precision) {
double c = 0.5 * EPSILON * num;
// double p = Math.pow(10, precision); //slow
double p = 1; while (precision--> 0) p *= 10;
if (num < 0)
p *= -1;
return Math.round((num + c) * p) / p;
}
// testing edge cases
RoundCorrect(1.005, 2); // 1.01 correct
RoundCorrect(2.175, 2); // 2.18 correct
RoundCorrect(5.015, 2); // 5.02 correct
RoundCorrect(-1.005, 2); // -1.01 correct
RoundCorrect(-2.175, 2); // -2.18 correct
RoundCorrect(-5.015, 2); // -5.02 correct
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-07-02 16:45:24