1350

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?

rm-green
  • 25
  • 4
Alex Spurling
  • 47,884
  • 23
  • 63
  • 71

36 Answers36

812

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.

fishinear
  • 5,674
  • 3
  • 32
  • 80
curtisk
  • 18,798
  • 4
  • 50
  • 68
  • 9
    This is probably the best solution presented so far. The reason I didn't spot this facility when I first looked at the DecimalFormat class is that it was only introduced in Java 1.6. Unfortunately I'm restricted to using 1.5 but it will be useful to know for the future. – Alex Spurling Oct 01 '08 at 13:07
  • Doesn't work with exponent decimalformats, say format("0.0E00"). It will in this example round 0.0155 to 0.0E00 instead of 1.6E-02. – Martin Clemens Bloch Oct 15 '14 at 23:50
  • 1
    I tried this with: `"#.##"`, rounding `HALF_UP`. `256.335f` -> `"256.33"` ...(example comes from comments to @asterite's answer). – bigstones Dec 11 '15 at 11:43
  • 6
    Please be carefull as DecimalFormat depend on your current Local configuration, you may not get a dot as a separator. I personnally prefer Asterite's answer below – Gomino Mar 02 '16 at 17:01
  • 1
    Also be aware that you should not expect DecimalFormat to be thread-safe. As per [Java docs](https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html): _Decimal formats are generally not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally._ – CGK Aug 10 '16 at 03:05
  • 1
    how do i make it so that it does a proper rounding so it will not round 0.0004 to 0.001 –  Oct 20 '16 at 08:00
  • Cannot get this working with HALF_UP: Example `DecimalFormat df = new DecimalFormat("0.00"); df.setMaximumFractionDigits(2); df.setRoundingMode(RoundingMode.HALF_UP); df.format(3.775)` returns 3.77 – Thorsten Niehues Dec 11 '17 at 14:20
  • 1
    It's not too difficult to create cases where this simply doesn't work. I wouldn't use this method if it's important to get the correct result. – Dawood ibn Kareem Feb 20 '18 at 02:04
  • 1
    @ThorstenNiehues Just because you specify it as 3.775, does not mean it has that value internally. Internally it has a binary value, and 3.775 cannot be represented exactly as a binary value. So it might have a value corresponding to 3.77499999999 internally. When rounding, always add the expected accuracy of the value. – fishinear Oct 25 '19 at 15:51
491

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.

confile
  • 29,115
  • 44
  • 187
  • 340
asterite
  • 7,387
  • 2
  • 21
  • 18
  • 1
    Math.round uses an internal cast to long, which you are then casting back to double. – Chris Cudmore Sep 30 '08 at 16:22
  • 1
    I think this is better than using DecimalFormat though. DecimalFormat will allocate various objects implicitly, and also a String on each call to decimalFormat.Format(). I would image it's better to cast to a few primatives than allocate objects. – Andi Jay Jul 09 '12 at 20:01
  • 76
    UPDATE: I just confirmed that doing this IS WAY faster than using DecimalFormat. I looped using DecimalFormat 200 times, and this method. DecimalFormat took 14ms to complete the 200 loops, this method took less than 1ms. As I suspected, this is faster. If you get paid by the clock cycle, this is what you should be doing. I'm surprised Chris Cudmore would even say what he said to be honest. allocating objects is always more expensive than casting primitives and using static methods (Math.round() as opposed to decimalFormat.format()). – Andi Jay Jul 10 '12 at 14:35
  • 3
    @Andi Jay I'm not saying you're wrong or right, but you can't really say that an isolated test on a single machine confirms your theory. – b1nary.atr0phy Aug 25 '12 at 12:33
  • 109
    This technique fails in over 90% of cases. -1. – user207421 Oct 02 '12 at 03:12
  • 25
    Indeed, this fails: `Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775`. – Robert Tupelo-Schneck Oct 03 '12 at 18:51
  • 3
    I think doing multiplication will be faster than division, so `(double)Math.round(value * 100000) * 0.000001` – Alvin Wong Jan 15 '13 at 15:19
  • I used this method for a long time, but now realized it was not the way to go – Victor P. Mar 19 '13 at 22:54
  • 5
    @RobertTupelo-Schneck This does not work, because double only has a precision of approximately 14 decimal places (anything more than that will not be accurate anyway) – sambe Aug 19 '13 at 14:18
  • 57
    Be very careful when using this method (or any rounding of floating points). It fails for something as simple as 265.335. The intermediate result of 265.335 * 100 (precision of 2 digits) is 26533.499999999996. This means it gets rounded down to 265.33. There simply are inherent problems when converting from floating point numbers to real decimal numbers. See EJP's answer here at http://stackoverflow.com/a/12684082/144578 – Sebastiaan van den Broek Nov 14 '13 at 13:51
  • 1
    @ChrisCudmore has the best answer here scroll down now, also Math.pow(10,20) is way too big, if you need 20 decimal places of precision then double is not for you. – satur9nine Apr 10 '14 at 17:21
  • 2
    This fails with very small values too: `(double)Math.round(1.005 * 100) / 100 == 1.0` Don't use it! – Matthias Braun May 19 '14 at 14:23
  • 2
    1.005 == 1.00 and 265.335 == 265.33 -> so what! it is fine. there is conversions of floating point going into round, there is conversions of floating point going into the division, there is floating point conversions going into 100.0 you just have to accept that floating point is FLOATING POINT... it is approximation! of decimals. floating point double is fast!!! sure you lose some precision, but who cares.. its super duper fast! – hamish Jul 13 '14 at 07:56
  • 1
    sure you lose some tincy wincy precision on the ROUND_EVEN/ROUND_UP on those fringy cases, but who cares.. its super duper fast! that is why programmers use double in the first place. you are rounding those extras off the end anyway so they are obviously not significant to you or your users. otherwise you would not be using double (aka floating point) in the first place. – hamish Jul 13 '14 at 08:04
  • 5
    @AndiJay: "If you get paid by the clock cycle, this is what you should be doing" -- I disagree. If I was paid by clock cycle, I would use the `DecimalFormat` to make my code as slow as possible: the more clock cycles it requires, the more money for me ;) – Franz D. Jul 15 '15 at 07:38
  • 2
    for speed, I have converted to an int before where $5.00 became 500. Super fast math, always rounding to 2 decimal points, and display only requires a divide by 100. – darren Aug 05 '15 at 17:54
  • 9
    @SebastiaanvandenBroek: Wow I never knew it was that easy to get a wrong answer. However, if one is working with non-exact numbers, one must recognize that any value *is not exact*. `265.335` really means `265.335 += tolerance`, where tolerance depends on previous operations and range of input values. We do not know the true, exact value. **At the edge values, *either* answer is arguably correct.** If we need to be exact, we shouldn't work in double. The `fail` here isn't in converting back to double. Its in OP thinking he can rely on the incoming `265.335` as being exactly that. – ToolmakerSteve Aug 28 '15 at 03:17
  • 1
    I don't think the `(double)` cast is necessary. – shmosel Sep 08 '16 at 06:16
  • @ToolmakerSteve When the initial number has three decimals and you want only two, this gives you the right (`HALF_EVEN` rounded) answer: `x = Math.rint(1000*x); x = Math.rint(x/10.0); return x / 100.0;`. Obviously, the result is not exactly `365.34`, but it's the closest approximation and it prints out like this. – maaartinus Jun 21 '17 at 04:47
  • This method method will never work reliably. The reason is that the result is a not a string but a double value, which has a binary representation internally. But the result will likely not be representable as a binary number. – fishinear Oct 25 '19 at 15:55
202
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));
    }
Nav
  • 16,995
  • 26
  • 78
  • 120
MetroidFan2002
  • 27,537
  • 16
  • 60
  • 79
  • 41
    That's my preferred solution. Even shorter: BigDecimal.valueOf(doubleVar).setScale(yourScaleHere, BigDecimal.ROUND_HALF_UP); BigDecimal.valueOf(double val) actually calls Double.toString() under the hood ;) – Etienne Neveu Feb 09 '10 at 10:59
  • 4
    Nice. Don't cut corners and use `new BigDecimal(doubleVar)` as you can run into issues with rounding of floating points – Edd Jan 26 '15 at 17:57
  • 8
    @Edd, interestingly, the rounding issue occurs in the case SebastiaanvandenBroek mentions in comment to asterite's answer. `double val = 265.335;`, `BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();` => `265.34`, but `(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();` => `265.33`. – ToolmakerSteve Aug 28 '15 at 03:41
  • 7
    @ToolmakerSteve That's because using new BigDecimal with the double takes the double value directly and attempts to use that to create the BigDecimal, whereas when using BigDecimal.valueOf or the tostring form parses it to a string first (a more exact representation) before the conversion. – MetroidFan2002 Aug 30 '15 at 05:09
  • There's a big trade off between accuracy and speed, as the method specified by @asterite is much faster, but rounds to errors. In cases where multiple calls to this method here consume 120 ms, the other method (multiply/divide) consumes mere 7 ms. So if you're just removing decimals in order to store a GPS bearing with only one decimal into a JSON string, you probably don't need all the precision of this expensive method. – Daniel F May 19 '21 at 09:16
121

You can also use the

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

to make sure you have the trailing 0's.

Milhous
  • 14,003
  • 16
  • 60
  • 80
91

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
user207421
  • 289,834
  • 37
  • 266
  • 440
  • 9
    The trick is that in all of your 9251 errors, the printed result is still correct. – Didier L Aug 09 '13 at 07:52
  • 1
    @DidierL That proves that the 'printed result' and the 'result' aren't the same thing. The correctness of the 'printed result' is affected by what happens during printing. The multiply-and-divide alone doesn't solve the problem. – user207421 Aug 11 '13 at 01:03
  • 7
    @DidierL It doesn't surprise me. I had the very good fortune of doing 'Numerical Methods' as my very first computing course and being introduced right at the start to what floating-point can and cannot do. Most programmers are pretty vague about it. – user207421 Aug 13 '13 at 09:55
  • the same output was produced by the python version of this program. – ultrajohn Sep 02 '13 at 05:30
  • hmm, it seems that there is an error in your program. System.out.println("a="+a+" (a % *.0001*)="+(a % *0.001*)); – ultrajohn Sep 02 '13 at 05:46
  • Well, I confess I'm pretty vague about these 'Numerical Methods'. If you have some time, I'd love your insight on [an earlier question of mine](http://stackoverflow.com/questions/17120806/ordering-operation-to-maximize-double-precision). – Matthieu Oct 19 '13 at 06:04
  • 4
    While the original point stands (truncation of a floating-point is not the same as decimal rounding), this counter-example is a little bit suspect to me. Note that we know the double 0.25 is exactly equal to 1/4, yet `((0.25 % 0.01) == 0.0)` evaluates to false. – Alex Oct 25 '13 at 17:27
  • 2
    I would change the test from `if ((d % 0.01) != 0.0)` to `if (BigDecimal.valueOf(d).compareTo(new BigDecimal(d)) != 0)`, which indicates that the error rate is even higher than originally estimated (and increases with the scale, up to 99.9% for a scale of 5) – Alex Oct 25 '13 at 17:44
  • 3
    There's an explanation: (d % 0.01) adds inaccuracy to the result and shadows the precision of the rounding operation. So it only proves that 92% of the time the modulus operation is not precise. I have a counter example:`code double d1, d2; d1 = 10.0100000000000000000123D; d2 = 10.0100000D; System.out.println(Math.round(d1 * 100)/100D == d2); // true double d3 = 0.0000090000000000000000000789D; System.out.println(Math.round(d3 * 100)/100D == 0.0D); // true` BTW, I'm not advocating this technique. It's prone to a possible overflow. – Yuri Nov 27 '13 at 12:06
  • 16
    All you are doing is refuting that floating doesn't represent many decimal values exactly, which I would hope we all understand. Not that rounding does causes a problem. As you admit, the numbers still print as expected. – Peter Lawrey Mar 02 '14 at 11:21
  • 9
    Your test is broken, take round() out and the test fails 94% of the time. http://ideone.com/1y62CY prints `100 trials 94 errors` You should start with a test which passes, and show that introducing rounding breaks the test. – Peter Lawrey Mar 02 '14 at 11:26
  • 6
    Refutation, refuted here. Using Math.round for this range of `double` as no errors http://ideone.com/BVCHh3 – Peter Lawrey Mar 02 '14 at 11:42
  • 1
    @PeterLawrey Good point, but it's only true if it's impossible to round .001 to an exact number of decimal places, which is *quod erat demonstrandum.* – user207421 Apr 03 '14 at 20:43
  • yeah exactness would mean 100 times more memory usage, and exactness would mean 100 times slower. draw your own conclusions as to why programmers and cpu's love floating point doubles :) in 50 years time when cpu's are 10,000 times faster.. nobody is going to care about doubles anymore :) even now we are seeing faster quad ARM android processors... that is why people already on this thread want exactness over speed. – hamish Sep 04 '15 at 00:07
  • 1
    @ToolmakerSteve The question is about getting exactly *n* decimal places. Any other result is off-topic, as are your remarks about my attitude. – user207421 Jan 27 '16 at 03:00
  • @hamish It requires a decimal radix, not 100 times more memory. – user207421 Jan 27 '16 at 03:01
  • While I agree with you, as `0.01` cannot be represented exactly, this test is bad. A better test would be to convert the result of `roundOff` to `BigDecimal`, and compare it to the exact result calculated with `BigDecimal`. – geza Oct 05 '17 at 11:18
  • @geza I redid the loop part using `BigDecimal/MathContext` with 16 digits of precision for the modulus part and I got 50% failures. – user207421 Dec 18 '17 at 03:48
  • `a *= temp;` has an imprecision in rounding problem values near a boundary. E.g. x.xx5 and `position == 2`. The product saved in `a` incurs a rounding that will result in the wrong `roundOff()` value from time to time. It would have made more sense here to maintain the extra precision of `double` with `a = Math.round(a * temp);` rather than `a *= temp; a = Math.round(a);` – chux - Reinstate Monica Feb 27 '18 at 12:56
  • @chux-ReinstateMonica That isn't the underlying problem. You can't get a quart out of a pint pot. – user207421 May 19 '21 at 10:25
87

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

Basil Bourque
  • 218,480
  • 72
  • 657
  • 915
user593581
  • 895
  • 6
  • 2
  • 2
    I think this is the best solution for Java 1.5 users (and below). One comment tho, don't use the HALF_EVEN rounding mode since it has diff behavior for odd and even numbers (2.5 rounds to 2 while 5.5 rounds to 6, for example), unless this is what you want. – IcedDante Jul 16 '12 at 19:11
  • 5
    The first solution is correct: the second one doesn't work. See [here](http://stackoverflow.com/a/7593617/207421) for proof. – user207421 Mar 19 '13 at 23:27
  • 1
    @EJP: Even the first solution with `RoundingMode.HALF_UP` is wrong. Try it with `1.505`. The right way is to use `BigDecimal.valueOf(d)`. – Matthias Braun Mar 29 '14 at 00:58
  • Matthias Braun, the solution is fine, hence 31 ups.. 1.505 decimal is stored in floating point double as 1.50499998 if you want to take 1.505 and convert from double to decimal, then you have to convert it to Double.toString(x) first then put it into a BigDecimal(), but that is extremely slow, and defeats the purpose of using double for speed in the first place. – hamish Jul 13 '14 at 08:22
  • 1
    Ran a loop of 100k with BigDecimal (took 225 ms) and Math.round (2 ms) way and here is the timing...Time Taken : 225 milli seconds to convert using to : 9232.13 Time Taken : 2 milli seconds to convert to : 9232.13 http://www.techiesinfo.com – user1114134 Jul 31 '14 at 19:32
  • this solution is 112 times slower than other methods. I guess if you do not care about writing fast code, why use a double in the first place. if you want proper base 10 numbers, then NEVER use a double in the first place. – hamish Sep 04 '15 at 00:00
  • @IcedDante The `HALF_EVEN` mode is known as [“Banker's rounding”](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even) often used in financial matters (thus the name). This approach is more fair mathematically than the [“Schoolhouse rounding”](https://en.wikipedia.org/wiki/Rounding#Round_half_up) typically taught to children. Since 5 is exactly in the middle, always rounding up ("Schoolhouse") **biases results to larger numbers**. Banker's Rounding splits the difference, so half the values round up and half round down (given a random distribution of values). – Basil Bourque Sep 14 '15 at 22:27
  • The first solution is also incorrect in a special case: BigDecimal bd = new BigDecimal(12.475d).setScale(2, RoundingMode.HALF_EVEN); bd.doubleValue(); --> Result: 12.47 The correct way would be to do: BigDecimal bd = new BigDecimal(Double.toString(12.475d)).setScale(2, RoundingMode.HALF_EVEN); Reason: new BigDecimal(12.475d) creates a BigDecimal with value 12.4749999999999996447286321199499070644378662109375 – stefan.m Feb 18 '16 at 13:18
  • You want `BigDecimal.valueOf(d)` instead of `new BigDecimal(d)` if you want to avoid errors due to floating point inaccuracy. – Dawood ibn Kareem Feb 20 '18 at 03:13
63

You can use the DecimalFormat class.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));
JibW
  • 4,347
  • 14
  • 61
  • 100
  • Any reason why `Double.valueOf()` was chosen over `Double.parseDouble()`? The `valueOf()` method returns a `Double` object, while `parseDouble()` will return a `double` primitive. With the way the current code is written, you also apply auto-unboxing to the return to cast it to the primitive that your `twoDouble` variable expects, an extra bytecode operation. I'd change the answer to use `parseDouble()` instead. – ecbrodie Dec 03 '15 at 06:25
  • `Double.parseDouble()` needs `String` input. – Ryde May 05 '16 at 23:40
42

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

UPDATE: BigDecimal.ROUND_HALF_UP is deprecated - Use RoundingMode

BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
Md. Farhan Memon
  • 5,727
  • 2
  • 8
  • 35
Ovesh
  • 4,831
  • 9
  • 49
  • 69
32
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
Chris Cudmore
  • 28,156
  • 12
  • 52
  • 92
  • 2
    yes this is exactly what math.round does for positive numbers, but have you tried this with negative numbers? people are using math.round in the other solutions to also cover the case of negative numbers. – hamish Jul 13 '14 at 08:39
  • Note: `Math.floor(x + 0.5)` and `Math.round(x)` – Peter Lawrey Feb 02 '18 at 11:25
31

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

Paŭlo Ebermann
  • 68,531
  • 18
  • 138
  • 203
Ivan
  • 311
  • 3
  • 3
  • 2
    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. – Paŭlo Ebermann Jul 03 '11 at 19:57
20

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)
    
Community
  • 1
  • 1
Mifeet
  • 10,908
  • 3
  • 50
  • 92
19

You could use the following utility method-

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}
Amit
  • 225
  • 2
  • 4
  • @mariolpantunes: It will fail. Try this: `round(1.005,2);` or `round(0.50594724957626620092, 20);` – Matthias Braun Mar 29 '14 at 01:02
  • It works. But uninformatively float and doubles are approximations. Let us consider your first example. If you print the output of interestedInZeroDPs before Math.round it will print 100.49999999999999. You lost precision as such Math.round round it as 100. Due to the nature or floats and doubles there are borderlines cases when it does not work properly (more information here http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems) – mariolpantunes Mar 31 '14 at 09:04
  • double is a fast! decimal is slow. computers don't bother processing their thinking in decimal notation. you have to give up some decimal precision to keep floating point double fast. – hamish Jul 13 '14 at 09:16
  • @hamish The question is about precision, not about speed. – user207421 Apr 25 '16 at 10:00
15

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://stackoverflow.com/a/22186845/212950 Thanks to jpdymond for offering this.

MAbraham1
  • 1,534
  • 4
  • 25
  • 40
9

You can use 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);

Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

Easwaramoorthy K
  • 3,687
  • 7
  • 33
  • 59
8

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

HarshitMadhav
  • 3,687
  • 5
  • 33
  • 43
Ivan
  • 89
  • 1
  • 1
7

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;
        }
    }
}
Li Ying
  • 1,813
  • 21
  • 13
7

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

}
Andrei Lupsa
  • 2,496
  • 3
  • 22
  • 18
7

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.

Jorgesys
  • 114,263
  • 22
  • 306
  • 247
5

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.

marco
  • 611
  • 6
  • 12
  • Do you have metrics showing how efficient is your solution compared to the other ones? – iaforek May 19 '17 at 14:26
  • I haven't compared it with other solutions but there is a jmh benchmark available in the source code: https://github.com/tools4j/decimal4j/blob/master/src/jmh/java/org/decimal4j/jmh/DoubleRounderBenchmark.java I did run the benchmark on a VM, the results are available as csv file here: https://github.com/tools4j/decimal4j/wiki/Performance – marco May 19 '17 at 22:23
  • 1
    DoubleRounder fails for following cases: DoubleRounder.round(256.025d, 2) - expected: 256.03, actual: 256.02 or for DoubleRounder.round(260.775d, 2) - expected: 260.78, actual: 260.77. – iaforek Jun 01 '17 at 22:46
  • @iaforek: this is correct, because DoubleRounder performs mathematically correct rounding. However I admit that this is somewhat counterintuitive and will hence update my answer accordingly. – marco Jun 11 '17 at 23:45
5

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.

ashr
  • 249
  • 5
  • 11
  • Please include your reason for downvoting in the comment, otherwise that's what we call intimidation. – ashr Jul 30 '19 at 18:08
4

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 ***
Suragch
  • 364,799
  • 232
  • 1,155
  • 1,198
  • 1
    you are only solving the particular case of rounding to 0 decimals. The original question is more generic. – lukas84 Mar 05 '19 at 10:18
4

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;
Craigo
  • 2,630
  • 22
  • 18
  • This would fail in cases where the myVal is not less that 1 and with zeros after decimal beyond scale value. Say you have myVal = 9.00000000912385; The above will return 9.0. I think we should provide a solution that works in all cases of myVal. Not specifically for the value you stated. – tavalendo Jun 21 '19 at 20:57
  • @user102859 In your example, 9.0 is the correct result. I don't understand how this would fail. – Craigo Jun 26 '19 at 16:45
3

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.

Drew Noakes
  • 266,361
  • 143
  • 616
  • 705
3

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.

Se Song
  • 1,393
  • 2
  • 17
  • 30
3

Here is a better function that rounds edge cases like 1.005 correctly.

Simply, we add the smallest possible float value (= 1 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.

This is a little program to test it: ideone.com

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
public static double round(double num, int digits) {

    // epsilon correction
    double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
    double p = Math.pow(10, digits);
    return Math.round(n * p) / p;
}

// test rounding of half
System.out.println(round(0.5, 0));   // 1
System.out.println(round(-0.5, 0));  // -1

// testing edge cases
System.out.println(round(1.005, 2));   // 1.01
System.out.println(round(2.175, 2));   // 2.18
System.out.println(round(5.015, 2));   // 5.02

System.out.println(round(-1.005, 2));  // -1.01
System.out.println(round(-2.175, 2));  // -2.18
System.out.println(round(-5.015, 2));  // -5.02
Amr Ali
  • 1,315
  • 13
  • 10
3

here is my answer:

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

System.out.println(num); // 4.89
Md. Jamal Uddin
  • 500
  • 6
  • 6
3

I have used bellow like in java 8. it is working for me

    double amount = 1000.431;        
    NumberFormat formatter = new DecimalFormat("##.00");
    String output = formatter.format(amount);
    System.out.println("output = " + output);

Output:

output = 1000.43
Enamul Haque
  • 3,249
  • 1
  • 20
  • 32
3

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();
Chris Gerken
  • 15,735
  • 6
  • 41
  • 58
2

So after reading most of the answers, I realized most of them won't be precise, in fact using BigDecimal seems like the best choice, but if you don't understand how the RoundingMode works, you will inevitable lose precision. I figured this out when working with big numbers in a project and thought it could help others having trouble rounding numbers. For example.

BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());

You would expect to get 1363.28 as an output, but you will end up with 1363.27, which is not expected, if you don't know what the RoundingMode is doing. So looking into the Oracle Docs, you will find the following description for RoundingMode.HALF_UP.

Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.

So knowing this, we realized that we won't be getting an exact rounding, unless we want to round towards nearest neighbor. So, to accomplish an adequate round, we would need to loop from the n-1 decimal towards the desired decimals digits. For example.

private double round(double value, int places) throws IllegalArgumentException {

    if (places < 0) throw new IllegalArgumentException();

    // Cast the number to a String and then separate the decimals.
    String stringValue = Double.toString(value);
    String decimals = stringValue.split("\\.")[1];

    // Round all the way to the desired number.
    BigDecimal bd = new BigDecimal(stringValue);
    for (int i = decimals.length()-1; i >= places; i--) {
        bd = bd.setScale(i, RoundingMode.HALF_UP);
    }

    return bd.doubleValue();
}

This will end up giving us the expected output, which would be 1363.28.

Alain Cruz
  • 3,588
  • 3
  • 17
  • 31
1

the following method could be used if need double

double getRandom(int decimalPoints) {
    double a = Math.random();
    int multiplier = (int) Math.pow(10, decimalPoints);
    int b = (int) (a * multiplier);
    return b / (double) multiplier;
}

for example getRandom(2)

Dmitry Fisenko
  • 148
  • 2
  • 16
1
  1. In order to have trailing 0s up to 5th position
DecimalFormat decimalFormatter = new DecimalFormat("#.00000");
decimalFormatter.format(0.350500); // result 0.350500
  1. In order to avoid trailing 0s up to 5th position
DecimalFormat decimalFormatter= new DecimalFormat("#.#####");
decimalFormatter.format(0.350500); // result o.3505
Niraj
  • 459
  • 1
  • 4
  • 12
1
public static double formatDecimal(double amount) {
    BigDecimal amt = new BigDecimal(amount);
    amt = amt.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_EVEN);
    return amt.doubleValue();
}

Test using Junit

@RunWith(Parameterized.class)
public class DecimalValueParameterizedTest {

  @Parameterized.Parameter
  public double amount;

  @Parameterized.Parameter(1)
  public double expectedValue;

@Parameterized.Parameters
public static List<Object[]> dataSets() {
    return Arrays.asList(new Object[][]{
            {1000.0, 1000.0},
            {1000, 1000.0},
            {1000.00000, 1000.0},
            {1000.01, 1000.01},
            {1000.1, 1000.10},
            {1000.001, 1000.0},
            {1000.005, 1000.0},
            {1000.007, 1000.01},
            {1000.999, 1001.0},
            {1000.111, 1000.11}
    });
}

@Test
public void testDecimalFormat() {
    Assert.assertEquals(expectedValue, formatDecimal(amount), 0.00);
}
Milan Paudyal
  • 383
  • 6
  • 8
0

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

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

    double result = Math.round(value * p)/p;
aim
  • 65
  • 6
  • 1
    Produces `1.0` for `value = 1.005` and `dp = 2`. Use [this](https://stackoverflow.com/questions/153724/how-to-round-a-number-to-n-decimal-places-in-java#answer-4826827) instead. – Matthias Braun May 19 '14 at 14:34
  • it is ok Matt, your example is not valid. because 1.005 can not be represented in floating point double anyway. it has to stored really above or below 1.005 i.e. it is stored as double when you compile: 1.0049998 (it is not stored as decimal in your compiled code as you would have the readers believe) aim is correct, he is storing values as floating point double, where fringe cases like yours is insignificant anyway. if it was, then you would be using 3dp then converting it to decimal, then doing a decimal round function, just like the link you posted. – hamish Jul 13 '14 at 08:15
  • 1
    @hamish I don't see where Matthias 'would have the readers believe' any such thing as that the value is compiled as decimal. Don't put words into other people's mouths. – user207421 Jun 28 '15 at 13:02
0

Keep in mind that String.format() and DecimalFormat produce string using default Locale. So they may write formatted number with dot or comma as a separator between integer and decimal parts. To make sure that rounded String is in the format you want use java.text.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));

Will print in English locale (no matter what your locale is): 0.99 123.57 123.00

The example is taken from Farenda - how to convert double to String correctly.

pwojnowski
  • 333
  • 3
  • 7
0

A simple way to compare if it is limited number of decimal places. Instead of DecimalFormat, Math or BigDecimal, we can use Casting!

Here is the sample,

public static boolean threeDecimalPlaces(double value1, double value2){
    boolean isEqual = false;
    // value1 = 3.1756 
    // value2 = 3.17
    //(int) (value1 * 1000) = 3175
    //(int) (value2 * 1000) = 3170

    if ((int) (value1 * 1000) == (int) (value2 * 1000)){
        areEqual = true;
    }

    return isEqual;
}
-1

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.

Qamar
  • 3,993
  • 23
  • 42