If you do a lot of numerical calculations in Java where control over precision and rounding is important (especially currency-related calculations), the BigDecimal class should be your first port of call. They encapsulate an integer unscaled value, and a 32-bit precision scaling factor, which provides a large range of values.

If we define a variable called `dividendTax`

as a BigInteger like so:

**private** BigDecimal dividendTax;

with a scaling factor of 2 (for currency) and a suitable rounding mode:

**static** **final** Integer SCALE = 2;

**public** **static** **final** RoundingMode ROUND_MODE = RoundingMode.HALF_UP;

We can round and scale an intermediate BigInteger-based calculation to a Double value like so:

**public** Double getDividendTax() {

**return** dividendTax.setScale(Constants.SCALE, Constants.ROUND_MODE).doubleValue();

}

Operations like divide() are methods on the BigDecimal instances themselves:

**public** Double getMonthlyTaxableAmount() {

**return** annualDividendTax.divide(**new** BigDecimal(12.0).setScale(Constants.SCALE, Constants.ROUND_MODE).doubleValue();

}

The above code snippet is possibly dangerous, in that the divide() operation can throw an ArithmeticException if the result from divide() is an infinite expansion (e.g. 1 divided by 3). This happened to me a couple of times until I figured what was missing.

The key is to pass a MathContext instance which specifies the correct precision to use. By default, the BigDecimal arithmetical operators use unlimited precision, which will obviously fail if a division operation results in an infinite series. So you need to truncate the results using one of the predefined precision ranges:

**public** Double getMonthlyTaxableAmount() {

**return** annualDividendTax.divide(**new** BigDecimal(12.0), MathContext.DECIMAL32).setScale(Constants.SCALE, Constants.ROUND_MODE).doubleValue();

}

Keep this in mind if you are using division operations that may potentially give infinite-precision results.