0

I need to round numbers to two decimal places:

1.1245 → 1.13 1.1235 → 1.12

I have spent the last two days scouring StackOverflow, and I have been unable to get any solution I have found to work at all:

They all seem to simply truncate the number at the third decimal place, then round it from there, which is not what I am trying to do. I am trying to start at the place furthest to the right, and then begin rounding appropriately; 5-9 goes up, 0-4 has no effect and is dropped.

Here is the current code I am working with:

BigDecimal a = new BigDecimal("1.1245"); double b = Math.round(a.doubleValue() * 100) / 100; System.out.print(a.setScale(2, BigDecimal.ROUND_HALF_EVEN) + " : " + a.setScale(2, BigDecimal.ROUND_HALF_UP) + " : " + b); 

And here is the output straight from the console:

console output

The problem here is that I am expecting 1.13 to be the result in all of the above cases, as though the following process is followed:

1.1245 → 1.125 → 1.13 1.1235 → 1.124 → 1.12 
21
  • 5
    your rounding rule is quite uncommon Commented Jan 6, 2015 at 18:05
  • 6
    what you are saying is that 1.1244 -> 1.12 and 1.245 -> 1.13? (no one does that) Commented Jan 6, 2015 at 18:07
  • 1
    Why would this be what you want? 1.1245 is strictly closer to 1.12 than it is to 1.13. Commented Jan 6, 2015 at 18:07
  • 1
    Yeah, the bug is in the spec Commented Jan 6, 2015 at 18:08
  • 3
    You could make a method that does in decremental steps a.setScale(i - 1, BigDecimal.ROUND_HALF_UP). But that is not the standard mathematical notion of rounding up. 1.1245 is rounded 1.2, as it is smaller than 1.250000. Is it a financial software scam? Commented Jan 6, 2015 at 18:10

3 Answers 3

1

I would test the distance with the standard rounding, then adjust and round again :

 for (String string : new String[] {"1.1245", "1.1244", "1.1235", "1.1249", "1.1299"}) { BigDecimal a = new BigDecimal(string); if (a.setScale(2, BigDecimal.ROUND_HALF_UP).subtract(a).compareTo(new BigDecimal("-0.0044")) < 0) { System.out.println(string + ":" + a.add(new BigDecimal("0.001")).setScale(2, BigDecimal.ROUND_HALF_UP)); } else { System.out.println(string + ":" + a.setScale(2, BigDecimal.ROUND_HALF_UP)); } } 

Result:

1.1245:1.13 1.1244:1.12 1.1235:1.12 1.1249:1.13 1.1299:1.13 
Sign up to request clarification or add additional context in comments.

1 Comment

I think that somebody who can needs to just delete this post to keep it from confusing anyone else. Also, thanks for the answer. I am just gonna stick with ROUND_HALF_UP and call it golden.
1

I think you should double check your spec, because the requirement is uncommon. Anyway, I think this does what you (seem to) need:

public BigDecimal round(BigDecimal n, int scale) { if (n.scale() > scale) { return round(n.setScale(n.scale() - 1, RoundingMode.HALF_UP), scale); } else { return n.setScale(scale, RoundingMode.UNNECESSARY); } } 

3 Comments

I think the OP expects round("1.124"); to give 1.12. Only 1.1245 and upward are supposed to give 1.13
Yeah, and I understand that now. And why it is uncommon. And mostly wrong. Fortunately, it wasn't the spec. It was my flawed understanding of how rounding works, which is why I expected the wrong result.
I adjusted my answer to satisfy the OP requirements. This recursive rounding function is to be called as in round(new BigDecimal("1.1245"), 2)
-1
public static double Rnd(double d) { d *= 100; d += .5; d = (int)d; d /= 100; return d; } 

This is the best way I have learned for rounding, as the two 100s can be adjusted to round to different places

2 Comments

I just saw the part about rounding in a weird way. This won't follow that rule. You may need to round to 1000s, then 100s, to fix that problem.
Hey at least I tried; I don't see many others posting answers

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.