Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes "Non-terminating decimal expansion" exception from BigDecimal.divide? [duplicate]

I've used BigDecimals before but not very often and I was working on something this morning and I kept getting the following exception:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.     at java.math.BigDecimal.divide(BigDecimal.java:1594) 

I was attempting to set the scale and use rounding to eliminate the problem like so:

    BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);     BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);     BigDecimal bd3 = bd1.divide(bd2).setScale(2,BigDecimal.ROUND_HALF_UP);     System.out.println("result: " + bd3); 

However, I keep getting the same exception. Anyone able to show me where I have made a mistake?

like image 643
ChadNC Avatar asked May 15 '12 15:05

ChadNC


People also ask

What is non-terminating repeating decimal expansion?

Non-Terminating, Non-Repeating Decimal. A non-terminating, non-repeating decimal is a decimal number that continues endlessly, with no group of digits repeating endlessly. Decimals of this type cannot be represented as fractions, and as a result are irrational numbers.

What is an example of a non-terminating decimal?

Example: 0.15, 0.86, etc. Non-terminating decimals are the one that does not have an end term. It has an infinite number of terms. Example: 0.5444444….., 0.1111111….., etc.

Does BigDecimal have decimal places?

Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point.

What is the limit of BigDecimal in Java?

The largest value BigDecimal can represent requires 8 GB of memory.


2 Answers

Non-terminating decimal need rounding

When using divide you should use a MathContext with RoundingMode in case the exact result has an infinite number of decimals.

Such is your case:

MathContext mc = new MathContext(2, RoundingMode.HALF_UP) ; BigDecimal bd3 = bd1.divide(bd2, mc); 

Alternatively call divide passing the scale and rounding mode.

BigDecimal bd3 = bd1.divide(bd2, RoundingMode.HALF_UP); 
like image 92
assylias Avatar answered Oct 14 '22 06:10

assylias


Here's the problem

bd1.divide(bd2) 

You need to use one of the overloaded divide() methods that takes a rounding mode (in various forms) - you cannot do the rounding after the division because with a nonterminating fraction the intermediate result would either already need to be rounded, or require infinite storage space.

like image 29
Michael Borgwardt Avatar answered Oct 14 '22 05:10

Michael Borgwardt