Commons-math rounding double
Asked Answered
T

3

6

I'm using commons-math 3.6.1.

I need to round a double value to 2 decimal

Let's assume this is my double value:

double d = 400.54540997260267;

Now by rounding this number I was expecting as result 400.54

Instead if my number was double d1 = 400.54640997260267; I was expecting as result 400.55

Now I'm using this code:

Precision.round(d, 2, BigDecimal.ROUND_DOWN);

If I use as roundingMethod BigDecimal.ROUND_DOWN I always get the lowest rounding. Which kind of rounding method should I use in order to get what I was expecting?

I tried the following code:

public class TestCalcoli

    {
        private static final Logger logger = LoggerFactory.getLogger(TestCalcoli.class.getName());
        private void calc(double d)
        {
            double result = Precision.round(d, 2, BigDecimal.ROUND_HALF_DOWN);
            double result2 = Precision.round(d, 2, BigDecimal.ROUND_HALF_UP);
            logger.info("d--> "+d+" result --> "+result+" result2 --> "+result2);
        }
        @Test
        public void calcola()
        {
            try
            {
                double d = 400.54540997260267;
                double d1 = 400.54640997260267;
                calc(d1);
                calc(d);
            }
            catch (Exception e)
            {
                logger.error("errore", e);
            }
        }
    }

CONSOLE OUTPUT:

2017-07-31 09:29:44,608 317  [main] INFO  i.e.c.r.pwb.test.TestCalcoli - d--> 400.54640997260265 result --> 400.55 result2 --> 400.55
2017-07-31 09:29:44,612 321  [main] INFO  i.e.c.r.pwb.test.TestCalcoli - d--> 400.54540997260267 result --> 400.55 result2 --> 400.55
Taxicab answered 31/7, 2017 at 7:18 Comment(1)
Providing your code definitely helps, but it would be better as a simple console app with a main method to make it trivial to run (no need to get a test environment up and running) - and include your actual results vs your expected results with each of your test cases.Irritable
B
6

You should use HALF_UP if you want to round up for same distance, i.e. digit 5.

Belamy answered 31/7, 2017 at 7:22 Comment(1)
Why this answer has so many upvotes if it doesn't even try to answer OP question? Did you at least read the question? OP wants something exactly oppositeInclinometer
H
4

Here are the available rounding methods suitable for your problem and their respective output for the two values:

Method             400.54540997260267    400.54640997260267
---------------    ------------------    ------------------
ROUND_CEILING      400.55                400.55
ROUND_DOWN         400.54                400.54
ROUND_FLOOR        400.54                400.54
ROUND_HALF_DOWN    400.55                400.55
ROUND_HALF_EVEN    400.55                400.55
ROUND_HALF_UP      400.55                400.55
ROUND_UP           400.55                400.55

None of the methods provide the results you expect.

The reason for this is because the two neighbors of 400.54540997260267 and 400.54640997260267 are 400.54 and 400.55. These neighbors are not equidistant from 400.54540997260267 or 400.54640997260267. Therefore, the HALF rounding methods always round to the nearest neighbor which in both cases is 400.55.

Borrowing from xenteros' answer, the desired results can be achieved using two rounding operations in succession. First round down with an extra digit of precision and then do the desired rounding with the desired precision:

double truncated = Precision.round(input, 3, BigDecimal.ROUND_FLOOR);
double rounded = Precision.round(truncated, 2, BigDecimal.ROUND_HALF_DOWN);
Hyson answered 1/8, 2017 at 12:55 Comment(0)
I
1

The easiest way to achieve what you want is to perform the following operations:

double d = 400.54540997260267;
Double temp = 1000*d;
temp = 1.0*temp.intValue()/1000;
Precision.round(temp, 2, BigDecimal.HALF_DOWN);

It removes digits from 4th decimal and then performs your desired rounding.

Inclinometer answered 1/8, 2017 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.