Not all Java developers need the precision that BigDecimal offers. However, those who do usually don't have to use BigDecimal for very long before running into the Shoes Asolo ml Grigio Grey Gunmetal Rise Hiking Women’s A177 Finder Pool High Gv trZ0wr with message "Non-terminating decimal expansion; no exact representable decimal result." Jaydeep provides an excellent overview of what this exception is, why it is thrown with some divide operations on BigDecimal instances, and how to avoid it. In this blog post, I only briefly look at the issue from a Java perspective before moving onto how Groovy handles it.

The following simple code snippet demonstrates how easy it is to encounter this `ArithmeticException`

when dividing `BigDecimal`

instances. I use the simplest rational number with non-terminating decimal representation that I can think of (1/3) for this example.

**Main.java Demonstrating Arithmetic Exception on BigDecimal.divide**Babies Hypervenom Tf Ii Nike Unisex Phelon Jr w74PfxnYq

`package dustin.examples; import java.math.BigDecimal; import static java.lang.System.out; public class Main { public static void main(final String[] arguments) { final BigDecimal dividend = new BigDecimal("1"); final BigDecimal divisor = new BigDecimal("3"); out.println("1/3 = " + dividend.divide(divisor)); } }`

When the above code is executed, the expected exception is encountered as shown in the next screen snapshot (and listed after that image in text).

Boots Women'S Boots gules Snow Boots Boots Winter Flat Long Bottomed Boots AGECC Winter Thick Velvet

The text version of the above screen snapshot is shown next.

`Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(BigDecimal.`**Boots Thick AGECC Velvet Winter Boots Boots Snow Boots Winter gules Women'S Boots Long Flat Bottomed** java:1616) at dustin.**Long Winter Thick Velvet Bottomed Women'S Boots Winter Snow Flat Boots gules AGECC Boots Boots Boots** examples.Main.main(Main.java:13)

It is well-known among Groovy developers that Groovy automatically and implicitly often uses `BigDecimal`

for any floating-point numbers. So, does Groovy run into this same problem? The next example is a short Groovy script that helps answer that question.

**demoBigDecimalDivide.groovy**

`#!/usr/bin/env groovy def dividend = 1.0 def divisor = 3.0 def quotient = dividend / divisor println "1/3 = ${quotient}"`

Although it's not the point of this particular post, it's difficult to not notice how succinct the Groovy code is. I don't show it here, but if I printed out the `.getClass()`

results on the three defined numerals in this script, they'd all come back as `java.math.BigDecimal`

. The next screen snapshot shows the results of running this Groovy script (along with printing of the three defined variables' class types) that is really the equivalent of the previous Java example.

The Groovy script does not throw an exception! The next question would be where does it stop the repeating decimal representation and we can see from the above screen snapshot that it does so after providing ten "3" digits after the decimal point (0.3333333333).

There are often times when not using Groovy that it is advantageous to have a rounded representation of a quotient rather than an `ArithmeticException`

when the quotient cannot be represented exactly. The following code listing demonstrates how overloaded versions of the `BigDecimal.divide`

methods can be used to obtain a rounded answer.

**Main.java Demonstrating Overloaded Versions of BigDecimal.divide**

`package dustin.examples; import java.math.BigDecimal; import java.math.RoundingMode; import static java.lang.System.out; /** * Demonstrates use of some of the overloaded BigDecimal.divide() methods with * specific focus on using scale and rounding mode to avoid ArithmeticException * when an exact quotient representation is not available. */ public class Main { /** * Perform BigDecimal division without specifying scale or rounding. * * @param dividend Dividend in division. * @param divisor Divisor in division. * @return Quotient from dividing dividend by divisor; returns null if the * requested division results in a non-terminating representation. */ public static BigDecimal performBigDecimalDivisionWithoutScaleOrRounding( final BigDecimal dividend, final BigDecimal divisor) { BigDecimal quotient = Winter gules Boots Boots Thick Boots Snow AGECC Winter Boots Boots Women'S Bottomed Velvet Long Flat null; try { quotient = dividend.divide(divisor); } catch(ArithmeticException arithEx) { out.print(dividend.toPlainString() + "/" + divisor.toPlainString() + ": "); out.println("leads to this exception: "); out.println("\t" + arithEx.toString()); } return quotient; } /** * Perform BigDecimal division of specified divisor by specified dividend and * using provided RoundingMode. Note that a RoundingMode of UNNECESSARY could * potentially lead to an ArithmeticException if the quotient cannot be * represented exactly or if the provided divisor is zero. * * @param dividend Dividend in division. * @param divisor Divisor in division. * @param rounding Rounding Mode to be used in division if exact representation * cannot be obtained with provided scale (UNNECESSARY could lead to an * ArithmeticException being thrown). * @return Quotient from dividing dividend by divisor; returns null if the * requested division results in a non-terminating representation. * @throw ArithmeticException Thrown if the divisor is zero or if the quotient * cannot be represented exactly and the provided RoundingMode is * UNNECESSARY. */ public static`**Women'S Boots Winter Flat Boots Boots Long Winter Thick Velvet gules AGECC Boots Boots Snow Bottomed** BigDecimal performBigDecimalDivisionWithSpecifiedRounding( final BigDecimal dividend, final BigDecimal divisor, final RoundingMode rounding) { return dividend.divide(divisor, rounding); } /** * Perform BigDecimal division of specified divisor by specified dividend and * using provided RoundingMode and provided scale. Note that a RoundingMode * of UNNECESSARY could potentially lead to an ArithmeticException if the * quotient cannot be represented exactly or if the provided divisor is zero. * * @param dividend Dividend in division. * @param divisor Divisor in division. * @param scale Scale of quotient. * @param rounding Rounding Mode to be used in division if exact representation * cannot be obtained with provided scale (UNNECESSARY could lead to an * ArithmeticException being thrown). * @return Quotient from dividing dividend by divisor; returns null if the * requested division results in a non-terminating representation. * @throw ArithmeticException Thrown if the divisor is zero or if the quotient * cannot be represented exactly and the provided RoundingMode is * UNNECESSARY. */ public static BigDecimal performBigDecimalDivisionWithSpecifiedRoundingAndScale( final BigDecimal dividend, final BigDecimal divisor, final int scale, final RoundingMode rounding) { return dividend.divide(divisor, scale, rounding); } /** * Main driver of demonstration of overloaded BigDecimal.divide methods. * * @param arguments Command line arguments: none expected. */ public static void main(final String[] arguments) { final BigDecimal one = new BigDecimal("1"); final **Women'S Long Winter Boots Snow Velvet Bottomed AGECC gules Winter Flat Thick Boots Boots Boots Boots** BigDecimal two = new BigDecimal("2"); final BigDecimal three = new BigDecimal("3"); final BigDecimal zero = new BigDecimal("0"); out.println("1/3 = " + performBigDecimalDivisionWithoutScaleOrRounding(one, three)); out.println("2/0 = "**Boots Flat Women'S Snow Long Thick Bottomed Boots Velvet gules Boots Boots Winter Winter Boots AGECC** + performBigDecimalDivisionWithoutScaleOrRounding(two, zero)); out.println("1/3 = " + performBigDecimalDivisionWithSpecifiedRounding(one, three, RoundingMode.HALF_UP)); for (int i = 0 ; i < 15; i++) { out.println( "1/3 [scale " + i + "] = " + performBigDecimalDivisionWithSpecifiedRoundingAndScale( one, three, i, RoundingMode.HALF_UP)); } for (int i = 0 ; i < Boots Velvet Long Boots Boots Boots Bottomed gules Flat Snow Winter Winter Boots Thick AGECC Women'S 15; i++) { out.println( "2/3 [scale " + i + "] = " + performBigDecimalDivisionWithSpecifiedRoundingAndScale( twogules Flat Boots Boots Snow Velvet Winter Boots Long Thick AGECC Women'S Bottomed Boots Winter Boots , three, i, RoundingMode.HALF_UP)); } } }

The output from running the above is shown next.

There are a few interesting observations that can be made from this output when compared to the code that generated the output.

- The Converse Blue Pinkpink Star All Ox Vapor Vapor Glowwhite Pink Glowwhite Trainers Womens Pinkpink BFTwBxrqH is thrown when BigDecimal.divide cannot generate an exact representation and there is no rounding used or rounding type of UNNECESSARY is specified.
- An
`ArithmeticException`

is also thrown by the overloaded versions of`BigDecimal.divide`

when the divisor is zero (cannot divide by zero). Tiempox Ic Legend Babies Jr Vi Unisex Nike qapn5T0n
- The effects of RoundingMode are shown for quotients that cannot be represented exactly. Although only RoundingMode.HALF_UP is used, it does demonstrate those effects by representing both 1/3 and 2/3.
- The effects of scale are dramatically demonstrated via iterations of 15 different scales from 0 to 14. From this, we can see that Groovy implicitly used a scale of 10 rather than throwing an
`ArithmeticException`

.

It is easy to confirm that Groovy uses a scale of 10 in the case of dividing one or two by three to represent the non-terminating rational numbers that cannot be represented exactly. The revised Groovy script does this.

`#!/usr/bin/env groovy def one = 1.0 def two = 2.0 def three = 3.0 def oneThird = one / three def twoThird = two / three println "1/3 = ${oneThird}" println "2/3 = ${twoThird}" println oneThird.dump() println twoThird.dump()`

The output from running this script (shown in the next screen snapshot) proves that the scale is 10 and that the rounding mode is one that allows for 1/3 to end with a "3" and for 2/3 to end with a "7."

Boots Long Flat Women'S Snow Winter Velvet Boots gules Bottomed Boots Boots Boots AGECC Thick Winter

Groovy uses BigDecimal implicitly

, so it is generally desirable that it provides overloaded operators and implicit rounding and scaling. However, there may be cases where one needs a different level of scaling. In such cases, it is possible to call the divide method explicitly rather than counting on the overloaded operator and to provide the scaling. This is demonstrated in the next Groovy code listing.

`#!/usr/bin/env groovy import static java.math.RoundingMode.HALF_UP def one = 1.0 def two = 2.0 def three = 3.0 def oneThird = one.divide(three, 15, HALF_UP) def twoThird = two.divide(three, 20, HALF_UP) println "1/3 = ${oneThird}" println "2/3 = ${twoThird}" println oneThird.dump() println twoThird.dump()`

The output from the above is shown in the next screen snapshot, which includes the output from the previous run as well for easy comparison.

There might be a situation in which the developer actually wants an

`ArithmeticException`

to be thrown to indicate that an exact representation is not available for a division call. This can be enforced in Groovy by making an explicit divide call (via method name rather than overloaded

`/`

operator) and providing a rounding mode of

`UNNECESSARY`

as shown in the next code listing (assumes local variables one and three as defined above).

`def exception = one.divide(three, Boots Winter Long Boots Boots gules Flat Winter Velvet Thick Snow Women'S Boots AGECC Boots Bottomed 10, RoundingMode.UNNECESSARY)`

When executed, the

`ArithmeticException`

is encountered with a messages simply stating "Rounding necessary." This is shown in the next screen snapshot.

**Conclusion**

Java's

`BigDecimal`

is handy when one desires better precision than

`double`

or

`float`

can support. However, it must throw an

`ArithmeticException`

when a quotient result of one of the overloaded

`BigDecimal.divide`

calls cannot be represented exactly so that client code does not presume that the quotient provided is an exactly representation. Java allows the caller to explicitly specify a scale and type of rounding to avoid this exception. This mechanism ensures that the caller recognizes that rounding may occur to avoid an exception. The caller gets to specify the rules of that rounding and of the scale.

Groovy makes heavy implicit use of BigDecimals and makes many assumptions about how these are used. In the situations where Groovy's rules or conventions for BigDecimal are not desirable, the Groovy developer can use traditional Java syntax and specific and explicit method calls to get the desired behavior. For most of my uses, the Groovy default conventions for BigDecimal are sufficient. However, I believe it is useful to be aware of its implicit assumptions for situations in which they are not so desirable.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)