upto How to round a number to n decimal places in Java




print upto 6 decimal places java (24)

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?


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 ***

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.


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.


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

Suppose you have

double d = 9232.129394d;

you can use BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

or without BigDecimal

d = Math.round(d*100)/100.0d;

with both solutions d == 9232.13


Try this: org.apache.commons.math3.util.Precision.round(double x, int scale)

See: 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

The internal implemetation of this method is:

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

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.


If you Consider 5 or n number of decimal. May be this answer solve your prob.

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

Output will be: 123.01
this can be solve with loop and recursive function.


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

If you're using a technology that has a minimal JDK. Here's a way without any Java libs:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;

Here is a summary of what you can use if you want the result as String:

  1. DecimalFormat#setRoundingMode():

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
    
  2. BigDecimal#setScale()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
    

Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):

  1. Precision from Apache Commons Math

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  2. Functions from Colt

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  3. Utils from Weka

    double rounded = Utils.roundDouble(0.912385, 5)
    

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.


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.


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

}

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

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.


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).


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

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

As some others have noted, the correct answer is to use either DecimalFormat or BigDecimal. Floating-point doesn't have decimal places so you cannot possibly round/truncate to a specific number of them in the first place. You have to work in a decimal radix, and that is what those two classes do.

I am posting the following code as a counter-example to all the answers in this thread and indeed all over (and elsewhere) that recommend multiplication followed by truncation followed by division. It is incumbent on advocates of this technique to explain why the following code produces the wrong output in over 92% of cases.

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

Output of this program:

10001 trials 9251 errors

EDIT: To address some comments below I redid the modulus part of the test loop using BigDecimal and new MathContext(16) for the modulus operation as follows:

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

Result:

10001 trials 4401 errors


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

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.





digits