How to round off a number to n decimal places in Java? [Answered]

Query explained:

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 next 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?

Round off a number to n decimal places in Java- Answer #1:

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

EDIT: The original answer does not address the accuracy of the double values. That is fine if you don’t care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:

Double d = n.doubleValue() + 1e-6;

To round down, subtract the accuracy.

Answer #2:

Assuming value is a double, you can do:

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

That’s for 5 digits precision. The number of zeros indicates the number of decimals.

Answer #3:

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

Answer #4:

You can also use the

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

to make sure you have the trailing 0’s.

Answer #5:

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 StackOverflow (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

Answer #6:

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

Answer #7:

You can use the DecimalFormat class.

double d = 3.76628729;

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

Answer #8:

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.

Hope you learned something from this post.

Follow Programming Articles for more!

About ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ

Linux and Python enthusiast, in love with open source since 2014, Writer at programming-articles.com, India.

View all posts by ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ →