13

I am developing a mathematical parser which is able to evaluate String like '5+b*sqrt(c^2)'. I am using ANTLR for the parsing and make good progress. Now I fell over the Java class BigDecimal and thought: hey, why not thinking about precision here.

My problem is that the Java API does not provide trigonometric methods for BigDecimals like java.lang.Math. Do you know if there are any good math libraries like Apache Commons out there that deal with this problem?

The other questions is how to realize the power method so that I can calculate 4.9 ^ 1.4 with BigDecimals. Is this possible?

A book request about numerical computing is also appreciated.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Marco
  • 133
  • 1
  • 1
  • 5
  • Why do you need BigDecimal for this? Aren't double good enough? – Jonas Jan 31 '10 at 22:01
  • BigDecimal is typically used for precision currency calculations. Are you sure double won't get you where you need to go? – Nick Jan 31 '10 at 22:05
  • If portability is important, then consider strictfp. (Might slow down the floating point arithmetic a bit though - I have never really benchmarked) – Ustaman Sangat Dec 15 '11 at 18:57

5 Answers5

7

BigDecimal does not provide these methods because BigDecimal models a rational number. Trigonometric functions, square roots and powers to non-integers (which I guess includes square roots) all generate irrational numbers.

These can be approximated with an arbitrary-precision number but the exact value can't be stored in a BigDecimal. It's not really what they're for. If you're approximating something anyway, you may as well just use a double.

Matt
  • 74,352
  • 26
  • 153
  • 180
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 6
    double does also approximate, but with a fixed size of bits. BigDecimals can use more bits. –  Dec 14 '15 at 22:41
  • `BigDecimal` is approximate; that's why if you try to do `BigDecimal.ONE.divide(BigDecimal.valueOf(3))`, you get a `java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.` Terminating equations work fine, but for non-terminating ones, you must specify an arbitrary precision. – Ky - Feb 28 '16 at 05:32
  • Any way you store a floating point number will be an approximation. For irrational numbers, exact values can't be stored in any format. – MiguelMunoz Jul 24 '23 at 10:58
7

ApFloat is a library which contains arbitrary-precision approximations of trigometric functions and non-integer powers both; however, it uses its own internal representations, rather than BigDecimal and BigInteger. I haven't used it before, so I can't vouch for its correctness or performance characteristics, but the api seems fairly complete.

Scott Fines
  • 759
  • 1
  • 5
  • 10
  • Just found it myself and have seen that it supports pretty much everything I need. I will keep you posted if everything works – Marco Feb 01 '10 at 21:34
4

The big-math library provides all the standard advanced mathematical functions (pow, sqrt, log, sin, ...) for BigDecimal.

https://github.com/eobermuhlner/big-math

Eric Obermühlner
  • 1,076
  • 9
  • 9
  • This library works great for populating accurate double values when I set the accuracy to 1074 decimal places, which is the maximum absolute value of the negative exponent of a Java primitive double value. – Al G Johnston Nov 25 '19 at 01:41
  • I don't think you need 1074 decimal places. The type double as defined in IEEE 754 binary64 is equivalent to MathContext.DECIMAL64 and has 16 digits precision for the mantissa. – Eric Obermühlner Nov 29 '19 at 09:40
  • To accurately calculate a double value I would use MathContext.DECIMAL128 (34 digits). Remember that precision is not the same thing as digits after the decimal point. Precision in this context refers to the number of significant digits. – Eric Obermühlner Nov 29 '19 at 09:50
0

Pretty much the best book on Numerical Computing would be Numerical Recipes

Reverend Gonzo
  • 39,701
  • 6
  • 59
  • 77
  • Only for some definitions of best. 'broadest' possibly, but always check the algorithms against other sources, and never use the implementations directly - at least if they haven't updated the 1 based indexing in the C version using undefined behaviour. – Pete Kirkham Jan 31 '10 at 22:47
0

Using an existing feature of Java BigDecimals, namely to allow limited precision arithmetic as described here, I recently implemented sqrt/1, exp/1, tan/1, etc.. for these number objects.

The numeric algorithms themselve use Maclaurin and Taylor series, plus appropriate range reductions to assure enough speed and breadth of the series.

Here is an example calculation, Ramanujan's Constant:

Jekejeke Prolog 2, Runtime Library 1.1.8
(c) 1985-2017, XLOG Technologies GmbH, Switzerland

?- use_module(library(stream/console)).
% 0 consults and 0 unloads in 0 ms.
Yes

?- X is mp(exp(pi*sqrt(163)), 60).
X = 0d262537412640768743.999999999999250072597198185688879353856320

The thingy was written in mixture of Prolog and Java. The speed and accuracy of it is still work in progress. The code is currently open source on GitHub.

Community
  • 1
  • 1