1

Problem description:

I am running performance test of calculation of PI number with primitives and with BigDecimal class.

Calculation of PI with primitives is around 5-6 times faster than the same algorithm, but with BigDecimal class.

I see a problem with creation of new BigDecimal object in the for loop, when adding values - see full code with line marked with comment.

Findings:

BigDecimal class has 3 methods which allows for addition

1.    public BigDecimal add(BigDecimal augend)
2.    public BigDecimal add(BigDecimal augend, MathContext mc)
3.    public static BigDecimal valueOf(long val) 

When using BigDecimal#valueOf method, the calculation time was even bigger than with new object creation.

Thus, the question - is it possible to increase performance of the calculation when using BigDecimal objects?

2

BigDecimal is based on a decimal representation of fractional numbers, and that's not the natural representation for a digital computer (Java is lacking something like BigBinaryFractional). On the other hand, double is a binary datatype directly supported by all modern CPUs. That's the first part of the performance difference.

In the lines

        double i2 = 4 * (pow / i1);
        pi = pi.add(new BigDecimal(i2));

you mix double and BigDecimal representations, needing conversions that further slow down the code.

And of course, double is a primitive, whereas BigDecimal is a reference type, so there's an overhead of object creation and later garbage collection.

So, I'm positively surprised that the difference is only a factor of 5.

  • true, but if there is a need to calculate longer PI value than 20 decimal digits (java.lang.Math.PI), we must use BigDecimal as double has limited precision. So in the program I used BigDecimal, unfortunatelly with lose of performance. So I do appericiate your response, but I do consider the question as not answered yet. – DevDio Sep 9 '17 at 20:01
  • @DevDio You didn't use BigDecimal very much. Try BigDecimal pow = BigDecimal.ONE.negate().pow(i); BigDecimal i1 = two.multiply(new BigDecimal(i)).add(BigDecimal.ONE); BigDecimal i2 = four.multiply(pow).divide(i1, MathContext.DECIMAL128); pi = pi.add(i2); (with two and four being BigDecimal 2 and 4) – Caleth Sep 11 '17 at 9:25
  • Note that MathContext.UNLIMITED results in "ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.", which is kind-of what we wanted here :( – Caleth Sep 11 '17 at 9:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.