BigDecimal format with DecimalFormat

I am trying to get predictable behavior with rounding BigDecimal numbers to the 15th digit. As a result, I get either rounded or rounded down.

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class NumberTest {
    public static void main(String[] args) {
        String pattern = "##############0.0##############";
        MathContext mc = new MathContext(15, RoundingMode.HALF_UP);
        NumberFormat numberFormat = new DecimalFormat(pattern);

        BigDecimal n1 = new BigDecimal(0.0452641706926935, mc);
        n1.setScale(15, BigDecimal.ROUND_HALF_UP);
        BigDecimal n2 = new BigDecimal(0.0123456789012345, mc);
        n2.setScale(15, BigDecimal.ROUND_HALF_UP);

        System.out.println("n1: "+n1+" ==> "+n1.doubleValue()+"="+numberFormat.format(n1.doubleValue()));
        System.out.println("n3: "+n2+" ==> "+n2.doubleValue()+"="+numberFormat.format(n2.doubleValue()));
    }
}

Output of my result:
n1: 0.0452641706926935 ==> 0.0452641706926935=0.045264170692694
n2: 0.0123456789012345 ==> 0.0123456789012345=0.012345678901234

      

n1 - rounded n2 - rounded

What am I missing?

thank.

+3


source to share


4 answers


You are not actually using BigDecimal, which you are setting the scale for:

n2.setScale(15, BigDecimal.ROUND_HALF_UP);

      

This line should be:



n2 = n2.setScale(15, BigDecimal.ROUND_HALF_UP);

      

Change to this and it works as expected.

+2


source


n2: 0.0123456789012345 ==> 0.0123456789012345=0.012345678901235

      

No, it n2

rounds up perfectly, the digit 15th

on n2 after the dot .

is equal to 4

, followed by 5

, so it 45

rounds to 5

.



if you count the number of digits after n2 .

, they are 16 digits

not 15

, so according to your pattern, you want to round the length 15 digit

after the dot.

btw you don't need to care about the number of digits before .

with "##############0.0##############"

, you can just use ".###############"

.

+1


source


You are setting the rounding mode for BigDecimal. But what rounds up the last part of your output is not BigDecimal. This is DecimalFormat.

Set the rounding mode to DecimalFormat:

numberFormat.setRoundingMode(RoundingMode.HALF_UP);

      

Note that DecimalFormat is capable of formatting instances of DecimalFormat. You shouldn't convert them to doubles before formatting them as you can lose precision by doing this.

+1


source


From the Java MathContext documentation:

The base-independent settings are:
precision: the number of digits to be used for an operation; results are rounded to this precision
roundingMode: a RoundingMode object which specifies the algorithm to be used for rounding.

      

You are not performing any operations here, so your BigInteger object is not rounded. So when you print your values, n1

and n2

still contain your initial 16-digit values.

Then I think you are getting rounding errors because of the method format

. A double argument is required as an argument, which will never exactly match 16 digits, but only approximations. Since this is an approximation, it n2

can be stored as ... 23449 instead of ... 2345.

But like Fev, I am not getting this error when executing your program on my computer.

+1


source







All Articles