MCPcopy Index your code
hub / github.com/eobermuhlner/big-math

github.com/eobermuhlner/big-math @v2.3.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.3.2 ↗ · + Follow
1,074 symbols 5,633 edges 55 files 325 documented · 30%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Build Status Code Coverage Quality Gate Status Open Issues Closed Issues Maven Central Last Commits Join the chat at https://gitter.im/eobermuhlner-big-math/community

<img alt="big-math" src="https://github.com/eobermuhlner/big-math/raw/v2.3.2/docs/images/big-math-splashscreen.png">

Advanced Java BigDecimal math functions (pow, sqrt, log, sin, ...) using arbitrary precision.

See also the official Big-Math Documentation.

BigDecimalMath

The class BigDecimalMath provides efficient and accurate implementations for:

  • log(BigDecimal, MathContext)
  • exp(BigDecimal, MathContext)
  • pow(BigDecimal, BigDecimal, MathContext) calculates x^y
  • sqrt(BigDecimal, MathContext)
  • root(BigDecimal, BigDecimal, MathContext) calculates the n'th root of x
  • sin(BigDecimal, MathContext)
  • cos(BigDecimal, MathContext)
  • tan(BigDecimal, MathContext)
  • asin(BigDecimal, MathContext)
  • acos(BigDecimal, MathContext)
  • atan(BigDecimal, MathContext)
  • atan2(BigDecimal, BigDecimal, MathContext)
  • sinh(BigDecimal, MathContext)
  • cosh(BigDecimal, MathContext)
  • tanh(BigDecimal, MathContext)
  • asinh(BigDecimal, MathContext)
  • acosh(BigDecimal, MathContext)
  • atanh(BigDecimal, MathContext)
  • toDegrees(BigDecimal, MathContext) converts from radians to degrees
  • toRadians(BigDecimal, MathContext) converts from degrees to radians
  • pow(BigDecimal, long, MathContext) calculates x^y for long y
  • factorial(int) calculates n!
  • bernoulli(int) calculates Bernoulli numbers
  • pi(MathContext) calculates pi to an arbitrary precision
  • e(MathContext) calculates e to an arbitrary precision
  • toBigDecimal(String) creates a BigDecimal from string representation (faster than BigDecimal(String))
  • mantissa(BigDecimal) extracts the mantissa from a BigDecimal (mantissa * 10^exponent)
  • exponent(BigDecimal) extracts the exponent from a BigDecimal (mantissa * 10^exponent)
  • integralPart(BigDecimal) extracts the integral part from a BigDecimal (everything before the decimal point)
  • fractionalPart(BigDecimal) extracts the fractional part from a BigDecimal (everything after the decimal point)
  • isIntValue(BigDecimal) checks whether the BigDecimal can be represented as an int value
  • isDoubleValue(BigDecimal) checks whether the BigDecimal can be represented as a double value
  • roundWithTrailingZeroes(BigDecimal, MathContext) rounds a BigDecimal to an arbitrary precision with trailing zeroes.

Usage

Mathematical calculations for BigDecimal

For calculations with arbitrary precision you need to specify how precise you want a calculated result. For BigDecimal calculations this is done using the MathContext.

MathContext mathContext = new MathContext(100);
System.out.println("sqrt(2)        = " + BigDecimalMath.sqrt(BigDecimal.valueOf(2), mathContext));
System.out.println("log10(2)       = " + BigDecimalMath.log10(BigDecimal.valueOf(2), mathContext));
System.out.println("exp(2)         = " + BigDecimalMath.exp(BigDecimal.valueOf(2), mathContext));
System.out.println("sin(2)         = " + BigDecimalMath.sin(BigDecimal.valueOf(2), mathContext));

will produce the following output on the console:

sqrt(2)        = 1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573
log10(2)       = 0.3010299956639811952137388947244930267681898814621085413104274611271081892744245094869272521181861720
exp(2)         = 7.389056098930650227230427460575007813180315570551847324087127822522573796079057763384312485079121795
sin(2)         = 0.9092974268256816953960198659117448427022549714478902683789730115309673015407835446201266889249593803

Since many mathematical constants have an infinite number of digits you need to specfiy the desired precision for them as well:

MathContext mathContext = new MathContext(100);
System.out.println("pi             = " + BigDecimalMath.pi(mathContext));
System.out.println("e              = " + BigDecimalMath.e(mathContext));

will produce the following output on the console:

pi             = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
e              = 2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427

Convenience methods for BigDecimal

Additional BigDecimalMath provides several useful methods (that are plain missing for BigDecimal):

MathContext mathContext = new MathContext(100);
System.out.println("mantissa(1.456E99)      = " + BigDecimalMath.mantissa(BigDecimal.valueOf(1.456E99)));
System.out.println("exponent(1.456E99)      = " + BigDecimalMath.exponent(BigDecimal.valueOf(1.456E99)));
System.out.println("integralPart(123.456)   = " + BigDecimalMath.integralPart(BigDecimal.valueOf(123.456)));
System.out.println("fractionalPart(123.456) = " + BigDecimalMath.fractionalPart(BigDecimal.valueOf(123.456)));
System.out.println("isIntValue(123)         = " + BigDecimalMath.isIntValue(BigDecimal.valueOf(123)));
System.out.println("isIntValue(123.456)     = " + BigDecimalMath.isIntValue(BigDecimal.valueOf(123.456)));
System.out.println("isDoubleValue(123.456)  = " + BigDecimalMath.isDoubleValue(BigDecimal.valueOf(123.456)));
System.out.println("isDoubleValue(1.23E999) = " + BigDecimalMath.isDoubleValue(new BigDecimal("1.23E999")));

will produce the following output on the console:

mantissa(1.456E99)      = 1.456
exponent(1.456E99)      = 99
integralPart(123.456)   = 123
fractionalPart(123.456) = 0.456
isIntValue(123)         = true
isIntValue(123.456)     = false
isDoubleValue(123.456)  = true
isDoubleValue(1.23E999) = false

The BigDecimalMath class is thread-safe and can be used in concurrent use cases.

Streams of BigDecimal

The class BigDecimalStream provides factory methods for streams of BigDecimal elements.

Overloaded variants of range(start, end, step) provide sequential elements equivalent to IntStream.range(start, end) but with configurable step (exclusive the end value).

Similar methods for the rangeClosed() (inclusive the end value) are available.

The streams are well behaved when used in parallel mode.

The following code snippet:

System.out.println("Range [0, 10) step 1 (using BigDecimal as input parameters)");
BigDecimalStream.range(BigDecimal.valueOf(0), BigDecimal.valueOf(10), BigDecimal.valueOf(1), mathContext)
    .forEach(System.out::println);

System.out.println("Range [0, 10) step 3 (using long as input parameters)");
BigDecimalStream.range(0, 10, 3, mathContext)
    .forEach(System.out::println);

produces this output:

Range [0, 10) step 1 (using BigDecimal as input parameters)
0
1
2
3
4
5
6
7
8
9

Range [0, 12] step 3 (using long as input parameters)
0
3
6
9
12

FAQ

Why do I have to pass MathContext to most functions?

Many mathematical functions have results that have many digits (often an infinite number of digits). When calculating these functions you need to specify the number of digits you want in the result, because calculating an infinite number of digits would take literally forever and consume an infinite amount of memory.

The MathContext contains a precision and information on how to round the last digits, so it is an obvious choice to specify the desired precision of mathematical functions.

What if I really do not want to pass the MathContext everytime?

The convenience class DefaultBigDecimalMath was added that provides mathematical functions where the MathContext must not be passed every time.

Please refer to the chapter DefaultBigDecimalMath

I specified a precision of n digits, but the results have completely different number of digits after the decimal point. Why?

It is a common misconception that the precision defines the number of digits after the decimal point.

Instead the precision defines the number of relevant digits, independent of the decimal point. The following numbers all have a precision of 3 digits: * 12300 * 1230 * 123 * 12.3 * 1.23 * 0.123 * 0.0123

To specify the number of digits after the decimal point use BigDecimal.setScale(scale, mathContext).

Why are BigDecimalMath functions so slow?

The mathematical functions in BigDecimalMath are heavily optimized to calculate the result in the specified precision, but in order to calculate them often tens or even hundreds of basic operations (+, -, *, /) using BigDecimal are necessary.

If the calculation of your function is too slow for your purpose you should verify whether you really need the full precision in your particular use case. Sometimes you can adapt the precision depending on input factors of your calculation.

How are the mathematical functions in BigDecimalMath calculated?

For the mathematical background and performance analysis please refer to this article: * BigDecimalMath

Some of the implementation details are explained here: * Adaptive precision in Newton’s Method

Why is there BigDecimalMath.toBigDecimal(String) if Java already has a BigDecimal(String) constructor?

The BigDecimal(String) constructor as provided by Java gets increasingly slower if you pass longer strings to it. The implementation in Java 11 and before is O(n^2).

If you want to convert very long strings (10000 characters or longer) then this slow constructor may become an issue.

BigDecimalMath.toBigDecimal(String) is a drop-in replacement with the same functionality (converting a string representation into a BigDecimal) but it is using a faster recursive implementation.

The following chart shows the time necessary to create a BigDecimal from a string representation of increasing length: toBigDecimal() precisions 0 to 100000

I only need a sqrt function - should I use this library?

Since Java 9 the BigDecimal class has a new function sqrt(BigDecimal, MathContext). If you only need the square root function then by all means use the provided standard function instead of this library.

If you need any other high level function then you should still consider using this library.

For high precision (above 150 digits) the current implementation of Java 9 BigDecimal.sqrt() becomes increasingly slower than BigDecimalMath.sqrt(). You should consider whether the increased performance is worth having an additional dependency.

The following charts shows the time needed to calculate the square root of 3.1 with increasing precision.

Java9 sqrt vs. sqrt() Java9 sqrt vs. sqrt()

Performance

The following charts show the time needed to calculate the functions over a range of values with a precision of 300 digits.

sqrt(), root(), exp(), sin(), cos() -10 to 10 sqrt(), root(), exp(), sin(), cos() 0 to 10 sqrt(), root(), exp(), sin(), cos() 0 to 100

exp(), log(), pow() 0 to 10 exp(), log(), pow() 0 to 100

BigComplex

The class BigComplex represents complex numbers in the form (a + bi). It follows the design of BigDecimal with some convenience improvements like overloaded operator methods.

A big difference to BigDecimal is that BigComplex.equals() implements the mathematical equality and not the strict technical equality. This was a difficult decision because it means that BigComplex behaves slightly different than BigDecimal but considering that the strange equality of BigDecimal is a major source of bugs we decided it was worth the slight inconsistency.

If you need the strict equality use BigComplex.strictEquals().

  • re
  • im
  • add(BigComplex)
  • add(BigComplex, MathContext)
  • add(BigDecimal)
  • add(BigDecimal, MathContext)
  • add(double)
  • subtract(BigComplex)
  • subtract(BigComplex, MathContext)
  • subtract(BigDecimal)
  • subtract(BigDecimal, MathContext)
  • subtract(double)
  • multiply(BigComplex)
  • multiply(BigComplex, MathContext)
  • `multiply(BigDecimal)

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Method 1,001
Class 52
Function 16
Enum 3
Interface 2

Languages

Java99%
TypeScript1%

Modules by API surface

ch.obermuhlner.math.big/src/test/java/ch/obermuhlner/math/big/BigDecimalMathTest.java204 symbols
ch.obermuhlner.math.big/src/main/java/ch/obermuhlner/math/big/BigFloat.java112 symbols
ch.obermuhlner.math.big/src/test/java/ch/obermuhlner/math/big/BigFloatTest.java75 symbols
ch.obermuhlner.math.big/src/test/java/ch/obermuhlner/math/big/BigRationalTest.java70 symbols
ch.obermuhlner.math.big/src/main/java/ch/obermuhlner/math/big/BigDecimalMath.java62 symbols
ch.obermuhlner.math.big/src/main/java/ch/obermuhlner/math/big/DefaultBigDecimalMath.java52 symbols
ch.obermuhlner.math.big/src/main/java/ch/obermuhlner/math/big/BigRational.java49 symbols
ch.obermuhlner.math.big.example/src/main/java/ch/obermuhlner/math/big/example/internal/PerformanceBigDecimalMath.java47 symbols
ch.obermuhlner.math.big.example/src/main/java/ch/obermuhlner/math/big/example/internal/BigDecimalMathExperimental.java47 symbols
ch.obermuhlner.math.big/src/test/java/ch/obermuhlner/math/big/DefaultBigDecimalMathTest.java45 symbols
ch.obermuhlner.math.big/src/test/java/ch/obermuhlner/math/big/BigComplexTest.java26 symbols
ch.obermuhlner.math.big/src/test/java/ch/obermuhlner/math/big/BigComplexMathTest.java24 symbols

For agents

$ claude mcp add big-math \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page