Set all BigDecimal operations to a certain precision?

(Almost) Original

Not as simple, but you can create a MathContext and pass it to all your BigDecimal constructors and the methods performing operations.

Revised

Alternatively, you can extend BigDecimal and override any operations you want to use by supplying the right MathContext, and using the rounding version of divide:

public class MyBigDecimal extends BigDecimal {

      private static MathContext context = new MathContext(120, RoundingMode.HALF_UP);

      public MyBigDecimal(String s) {
           super(s, context);
      }
      public MyBigDecimal(BigDecimal bd) {
           this(bd.toString()); // (Calls other constructor)
      }
      ...
      public MyBigDecimal divide( BigDecimal divisor ){
           return new MyBigDecimal( super.divide( divisor, context ) );
      }
      public MyBigDecimal add( BigDecimal augend ){
           return new MyBigDecimal( super.add( augend ) );
      }
      ...
}

You could create a class that extends BigDecimal and sets the precision automatically for you. Then you just use you that class.

public class MyBigDecimal extends BigDecimal {
      public MyBigDecimal(double d) {
           super(d);
           this.setScale(120, BigDecimal.ROUND_HALF_UP);
      }
      ...
}

Create a BigDecimalFactory class with static factory methods matching all constructors that accept MathContext - except that the MathContext instance is inside the factory and statically initialized at startup time. Here's a fragment:

public class BigDecimalFactory {
    public static BigDecimal newInstance (BigInteger unscaledVal, int scale) {
        return new BigDecimal (unscaledVal, scale, _mathContext);
    }

    // . . . other factory methods for other BigDecimal constructors

    private static final MathContext _mathContext = 
        new MathContext (120, BigDecimal.ROUND_HALF_UP);
}

Is there a way to set a 'global accuracy' for all BigDecimal calculations?

No.

You'll have to create a wrapper class that has a MathContext as an extra attribute. It will need to:

  • use this mc for each mathematical operation that would otherwise use the default semantics, and

  • create and return another wrapped instance each time the wrapped operation returns a regular instance.

(As a variation, you could implement a 'global' MathContext using a static, but you'll still need to use wrappering to ensure that the mc is used.)

(Extending BigDecimal would work too, and that is arguable neater than a wrapper class.)


You said this in a comment:

I really don't want to write my own Decimal module, I just want to understand why BigDecimal is being so uncooperative.

(Design questions can only be answered definitively by the design team. However ...)

As with all complicated utility classes, the design of BigDecimal is a compromise that is designed to meet the requirements of a wide range of use-cases. It is also a compromise between the competing meta-requirements (wrong word) of "powerfulness" and "simplicity".

What you have is a use-case that is not particularly well supported. But I suspect that if it was well supported (e.g. with a global MathContext controlling everything or a MathContext attached to each BigDecimal) then that would introduce all sorts of other complexities; e.g. dealing with operations where there are two or more competing context objects to consider. Such problems could be dealt with ... but they are liable to lead to "surprises" for the programmer, and that is not a good thing.

The current approach is simple and easy to understand, and if you need something more complicated you can implement it ... by explicitly supplying a MathContext for the operations that require it.