round - print upto 6 decimal places java




How to round a number to n decimal places in Java (20)

What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the previous number. This is the standard method of rounding most people expect in most situations.

I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.

I know one method of doing this is to use the String.format method:

String.format("%.5g%n", 0.912385);

returns:

0.91239

which is great, however it always displays numbers with 5 decimal places even if they are not significant:

String.format("%.5g%n", 0.912300);

returns:

0.91230

Another method is to use the DecimalFormatter:

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

returns:

0.91238

However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:

0.912385 -> 0.91239
0.912300 -> 0.9123

What is the best way to achieve this in Java?


@Milhous: the decimal format for rounding is excellent:

You can also use the

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

to make sure you have the trailing 0's.

I would add that this method is very good at providing an actual numeric, rounding mechanism - not only visually, but also when processing.

Hypothetical: you have to implement a rounding mechanism into a GUI program. To alter the accuracy / precision of a result output simply change the caret format (i.e. within the brackets). So that:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

would return as output: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

would return as output: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

would return as output: 0.9124

[EDIT: also if the caret format is like so ("#0.############") and you enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat does not produce any garbage (e.g. trailing zeroes) and will return: 3.1415926 .. if you're that way inclined. Granted, it's a little verbose for the liking of some dev's - but hey, it's got a low memory footprint during processing and is very easy to implement.]

So essentially, the beauty of DecimalFormat is that it simultaneously handles the string appearance - as well as the level of rounding precision set. Ergo: you get two benefits for the price of one code implementation. ;)


A succinct solution:

   public static double round(double value, int precision) {
      int scale = (int) Math.pow(10, precision);
      return (double) Math.round(value * scale) / scale;
  }

See also, https://.com/a/22186845/212950 Thanks to jpdymond for offering this.


Assuming value is a double, you can do:

(double)Math.round(value * 100000d) / 100000d

That's for 5 digits precision. The number of zeros indicate the number of decimals.


DecimalFormat is the best ways to output, but I don't prefer it. I always do this all the time, because it return the double value. So I can use it more than just output.

Math.round(selfEvaluate*100000d.0)/100000d.0;

OR

Math.round(selfEvaluate*100000d.0)*0.00000d1;

If you need large decimal places value, you can use BigDecimal instead. Anyways .0 is important. Without it the rounding of 0.33333d5 return 0.33333 and only 9 digits are allows. The second function without .0 has problems with 0.30000 return 0.30000000000000004.


I agree with the chosen answer to use DecimalFormat --- or alternatively BigDecimal.

Please read Update below first!

However if you do want to round the double value and get a double value result, you can use org.apache.commons.math3.util.Precision.round(..) as mentioned above. The implementation uses BigDecimal, is slow and creates garbage.

A similar but fast and garbage-free method is provided by the DoubleRounder utility in the decimal4j library:

 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 output

 0.667
 0.666
 1000.0
 9.00800700601E10

See https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

Disclaimer: I am involved in the decimal4j project.

Update: As @iaforek pointed out DoubleRounder sometimes returns counterintuitive results. The reason is that it performs mathematically correct rounding. For instance DoubleRounder.round(256.025d, 2) will be rounded down to 256.02 because the double value represented as 256.025d is somewhat smaller than the rational value 256.025 and hence will be rounded down.

Notes:

  • This behaviour is very similar to that of the BigDecimal(double) constructor (but not to valueOf(double) which uses the string constructor).
  • The problem can be circumvented with a double rounding step to a higher precision first, but it is complicated and I am not going into the details here

For those reasons and everything mentioned above in this post I cannot recommend to use DoubleRounder.


I came here just wanting a simple answer on how to round a number. This is a supplemental answer to provide that.

How to round a number in Java

The most common case is to use Math.round().

Math.round(3.7) // 4

Numbers are rounded to the nearest whole number. A .5 value is rounded up. If you need different rounding behavior than that, you can use one of the other Math functions. See the comparison below.

round

As stated above, this rounds to the nearest whole number. .5 decimals round up. This method returns an 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

Any decimal value is rounded up to the next integer. It goes to the ceiling. This method returns a 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

floor

Any decimal value is rounded down to the next integer. This method returns a 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

This is similar to round in that decimal values round to the closest integer. However, unlike round, .5 values round to the even integer. This method returns a 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 ***

If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.

Use BigDecimal or any other decimal-based format.

I do use BigDecimal for calculations, but bear in mind it is dependent on the size of numbers you're dealing with. In most of my implementations, I find parsing from double or integer to Long is sufficient enough for very large number calculations.

In fact, I've recently used parsed-to-Long to get accurate representations (as opposed to hex results) in a GUI for numbers as big as ################################# characters (as an example).


If you're using DecimalFormat to convert double to String, it's very straightforward:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

There are several RoundingMode enum values to select from, depending upon the behaviour you require.


In general, rounding is done by scaling: 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

Just in case someone still needs help with this. This solution works perfectly for me.

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();

}

returns a String with the desired output.


Real's Java How-to posts this solution, which is also compatible for versions before Java 1.6.

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();

Since I found no complete answer on this theme I've put together a class that should handle this properly, with support for:

  • Formatting: Easily format a double to string with a certain number of decimal places
  • Parsing: Parse the formatted value back to double
  • Locale: Format and parse using the default locale
  • Exponential notation: Start using exponential notation after a certain threshold

Usage is pretty simple:

(For the sake of this example I am using a custom locale)

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

Here is the class:

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), "");
    }

}

The code snippet below shows how to display n digits. The trick is to set variable pp to 1 followed by n zeros. In the example below, variable pp value has 5 zeros, so 5 digits will be displayed.

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();

To achieve this we can use this formatter:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

or:

DecimalFormat df = new DecimalFormat("0.00"); :

Use this method to get always two decimals:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Defining this values:

91.32
5.22
11.5
1.2
2.6

Using the method we can get this results:

91.32
5.22
11.50
1.20
2.60

demo online.


Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.

Example:

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));
}

gives the output:

12
123.1235
0.23
0.1
2341234.2125

Where dp = decimal place you want, and value is a double.

    double p = Math.pow(10d, dp);

    double result = Math.round(value * p)/p;


You can use the DecimalFormat class.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));

double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;

new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method, or the toPlainString method for Java 5+ for a plain format string.

Sample 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));
    }






digits