Class DefaultBigDecimalMath

java.lang.Object
ch.obermuhlner.math.big.DefaultBigDecimalMath

public class DefaultBigDecimalMath extends Object
A wrapper around BigDecimalMath that passes a current MathContext to the functions that need a MathContext argument.

The initial default MathContext is equivalent to MathContext.DECIMAL128 but this can be overridden by setting the following system properties:

  • ch.obermuhlner.math.big.default.precision to a positive integer precision (default=34)
  • ch.obermuhlner.math.big.default.rounding to a RoundingMode name (default=HALF_UP)

It is also possible to programmatically set the default MathContext using setDefaultMathContext(MathContext). It is recommended to set the desired precision in the MathContext very early in the startup of the application and to not change it afterwards.

Important: Avoid the pitfall of setting the precision temporarily using setDefaultMathContext(MathContext) for a calculation. This can lead to race conditions and calculations with the wrong precision if other threads in your application do the same thing.

To set a temporary MathContext you have to choice to use either:

  • DefaultBigDecimalMath.createLocalMathContext() in a try-with-resources statement
  • DefaultBigDecimalMath.withLocalMathContext() with a lambda function
Example code using DefaultBigDecimalMath.createLocalMathContext():
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
try (DefaultBigDecimalMath.LocalMathContext context = DefaultBigDecimalMath.createLocalMathContext(5)) {
    System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
    try (DefaultBigDecimalMath.LocalMathContext context2 = DefaultBigDecimalMath.createLocalMathContext(10)) {
        System.out.println("Pi[10]: " + DefaultBigDecimalMath.pi());
    }
    System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
}
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
 
Example code using DefaultBigDecimalMath.withLocalMathContext():
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
DefaultBigDecimalMath.withPrecision(5, () -> {
    System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
    DefaultBigDecimalMath.withPrecision(10, () -> {
        System.out.println("Pi[10]: " + DefaultBigDecimalMath.pi());
    });
    System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
});
System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
Both snippets with give the following ouput:
Pi[default]: 3.141592653589793238462643383279503
Pi[5]: 3.1416
Pi[10]: 3.141592654
Pi[5]: 3.1416
Pi[default]: 3.141592653589793238462643383279503

The temporary MathContext are stored in ThreadLocal variables and will therefore not conflict with each other when used in multi-threaded use case.

Important: Due to the ThreadLocal variables the local MathContext will not be available in other threads. This includes streams using parallel(), thread pools and manually started threads. If you need temporary MathContext for calculations then you must set the local MathContext inside every separate thread.

try (DefaultBigDecimalMath.LocalMathContext context = DefaultBigDecimalMath.createLocalMathContext(5)) {
    BigDecimalStream.range(0.0, 1.0, 0.01, DefaultBigDecimalMath.currentMathContext())
        .map(b -> DefaultBigDecimalMath.cos(b))
        .map(b -> "sequential " + Thread.currentThread().getName() + " [5]: " + b)
        .forEach(System.out::println);

    BigDecimalStream.range(0.0, 1.0, 0.01, DefaultBigDecimalMath.currentMathContext())
        .parallel()
        .map(b -> {
            try (DefaultBigDecimalMath.LocalMathContext context2 = DefaultBigDecimalMath.createLocalMathContext(5)) {
                return DefaultBigDecimalMath.cos(b);
            }
        })
        .map(b -> "parallel " + Thread.currentThread().getName() + " [5]: " + b)
        .forEach(System.out::println);
}