user2348709
user2348709

Reputation:

How to get high precision answers when using double values in Java?

I am just trying to get an understanding of how to calculate various values when working in java. I started out by learning about the BigDecimal class and how I can use that to calculate with high precision. I understand the following concept:

    BigDecimal xx = BigDecimal.valueOf(0.1);
    BigDecimal yy = BigDecimal.valueOf(0.2);


    System.out.printf("Number is: %s", xx.add(yy,new MathContext(30, RoundingMode.HALF_DOWN)).toString());

I get the result I expect of 0.3. What I tried next and am still stuck on is displaying really long decimal values after the calculation. I have 2 examples.

    BigDecimal xx = BigDecimal.valueOf(0.111111111111111111111111111111);
    BigDecimal yy = BigDecimal.valueOf(0.001111111111111111111111111111);


    System.out.printf("Number is: %s", xx.add(yy,new MathContext(30, RoundingMode.HALF_DOWN)).toString());

The result should be 0.112222...222, but comes out to 0.1122222222222222111.

The second example is using subtract instead of add. The answer should be 0.11, but instead I end up with 0.1099999999999999889.

I guess my question comes in two parts. Part one consists of how I am able to fix the above examples to get a correct answer and Part two is a little more general. I ultimately want to run some physic calculations that I would like to have very high precision on, say 20-30 decimal places. How can I perform my calculations so that I am preserving my answers and display them with small rounding issues and/or truncation?

Upvotes: 1

Views: 775

Answers (3)

Stephen C
Stephen C

Reputation: 718798

This is the hard part of your Question:

I ultimately want to run some physic calculations that I would like to have very high precision on, say 20-30 decimal places. How can I perform my calculations so that I am preserving my answers and display them with small rounding issues and/or truncation?

There is no simple answer to this. It really depends on the nature of the "physics calculation". Some calculations are relatively immune to error; i.e. the rounding errors don't much affect the final answer. In other cases (e.g. with chaotic systems) the errors build up rapidly and eventually swamp the answer.

It can also matter how you do the calculations. For instance there is one basic statistical calculation that involves calculation the difference between two "sums of squares" (or something like that). The SoS values are typically very large, but the difference is small. If you do the calculation the wrong way you get an imprecise value for the difference. Another problem where how you do the calculation can matter is matrix inversion.

For what it is worth, there is a branch of mathematics that deals with numerical calculations and accuracy. It is called Numerical Analysis. In "the good old days", it was part of Computer Science courses.

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533510

I guess my question comes in two parts. Part one consists of how I am able to fix the above examples to get a correct answer

Use the constructor which takes a String

BigDecimal xx = new BigDecimal("0.111111111111111111111111111111");
BigDecimal yy = new BigDecimal("0.001111111111111111111111111111");

Part two is a little more general. I ultimately want to run some physic calculations that I would like to have very high precision on, say 20-30 decimal places.

You should be are that BigDecimal can be 100x slower and there is very little in the real world you can measure to 15 digits of accuracy. I would rethink what "physic" problem really requires 20-30 digits of accuracy.

Upvotes: 2

Thilo
Thilo

Reputation: 262504

BigDecimal xx = BigDecimal.valueOf(0.111111111111111111111111111111);

You are using double literals here, that have a limited precision and a prone to rounding errors.

Use decimals all the way.

BigDecimal xx = new BigDecimal("0.111111111111111111111111111111");

Of course, if the long number is not something hard-coded into the program, but the result of a floating point calculation, then you already have the rounding error, and will have to live with it. Converting to BigDecimal cannot fix that anymore.

How can I perform my calculations so that I am preserving my answers and display them with small rounding issues and/or truncation?

Except for rounding when printing, there is not much you can do. Printf has format strings for that like "%.12d".

Upvotes: 5

Related Questions