24
votes

Which libraries for Java are there that have a fast implementation for floating point or fixed point operations with a precision of several thousands of digits? How performant are they?

A requirement for me is that it implements a multiplication algorithm that is better than the naive multiplication algorithm that takes 4 times as much time for a 2 times larger number of digits (compare Multiplication algorithms).

4
A general question from a standpoint of interest... what is your application that requires several thousand of digits decimal precision? - Simon
This is a hobby, not a job: I'd like to calculate some more digits of the en.wikipedia.org/wiki/Feigenbaum_constant - Hans-Peter Störr

4 Answers

41
votes

There are three libraries mentioned on the Arbitrary Precision Arithmetic page: java.math (containing the mentioned BigDecimal), Apfloat and JScience. I run a little speed check on them which just uses addition and multiplication.

The result is that for a relatively small number of digits BigDecimal is OK (half as fast as the others for 1000 digits), but if you use more digits it is way off - JScience is about 4 times faster. But the clear performance winner is Apfloat. The other libraries seem to use naive multiplication algorithms that take time proportional to the square of the number of digits, but the time of Apfloat seems to grow almost linearly. On 10000 digits it was 4 times as fast as JScience, but on 40000 digits it is 16 times as fast as JScience.

On the other hand: JScience provides EXCELLENT functionality for mathematical problems: matrices, vectors, symbolic algorithms, solution of equation systems and what not. So I'll probably go with JScience and later write a wrapper to integrate Apfloat into the algorithms of JScience - due to the good design this seems easily possible.

(UPDATE: I wrote a test suite for the number package of JScience and fixed a number of bugs. This went into release 4.3.1. So I can recommend checking it out.)

7
votes

Have you checked the performance of BigDecimal? I can't see anything obvious in the JavaDoc, but it would certainly be my first port of call.

3
votes

You could take a look at the JScience library and their Real number class. I'm not sure how the performance is relative to BigDecimal, but the goal of the library is to provide highly-tuned classes for scientific applications, which seems like a good sign.

-3
votes

Apfloat offers high precision on the mantissa, but appears to give less-than-usual precision on the exponent (based on the fact that it crashes with "Logarithm of zero" for values that double can handle). So it is not useful for big numbers.

Also, the documentation says:

"A pitfall exists with the constructors Apfloat(float,long) and Apfloat(double,long). Since floats and doubles are always represented internally in radix 2, the conversion to any other radix usually causes round-off errors, and the resulting apfloat won't be accurate to the desired number of digits.

For example, 0.3 can't be presented exactly in base 2. When you construct an apfloat like new Apfloat(0.3f, 1000), the resulting number won't be accurate to 1000 digits, but only to roughly 7 digits (in radix 10). In fact, the resulting number will be something like 0.30000001192092896... "

This appears to make Apfloat minimally useful.

BigDecimal does not have a logarithm function, and the documentation does not say whether it allows you to make bigger numbers than a double; the exponent is 32 bits, sort of.