ArithmeticException: "Non-terminating decimal expansion; no exact representable decimal result"
Solution 1
From the Java 11 BigDecimal
docs:
When a
MathContext
object is supplied with a precision setting of 0 (for example,MathContext.UNLIMITED
), arithmetic operations are exact, as are the arithmetic methods which take noMathContext
object. (This is the only behavior that was supported in releases prior to 5.)As a corollary of computing the exact result, the rounding mode setting of a
MathContext
object with a precision setting of 0 is not used and thus irrelevant. In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3.If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an
ArithmeticException
is thrown. Otherwise, the exact result of the division is returned, as done for other operations.
To fix, you need to do something like this:
a.divide(b, 2, RoundingMode.HALF_UP)
where 2 is the scale and RoundingMode.HALF_UP is rounding mode
For more details see this blog post.
Solution 2
Because you're not specifying a precision and a rounding-mode. BigDecimal is complaining that it could use 10, 20, 5000, or infinity decimal places, and it still wouldn't be able to give you an exact representation of the number. So instead of giving you an incorrect BigDecimal, it just whinges at you.
However, if you supply a RoundingMode and a precision, then it will be able to convert (eg. 1.333333333-to-infinity to something like 1.3333 ... but you as the programmer need to tell it what precision you're 'happy with'.
Solution 3
You can do
a.divide(b, MathContext.DECIMAL128)
You can choose the number of bits you want: either 32, 64 or 128.
Check out this link :
Solution 4
For fixing such an issue I have used below code
a.divide(b, 2, RoundingMode.HALF_EVEN)
2 is precision. Now problem was resolved.
Solution 5
I had this same problem, because my line of code was:
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
I change to this, reading previous Answer, because I was not writing decimal precision:
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
4 is Decimal Precison
AND RoundingMode are Enum constants, you could choose any of this
UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP
In this Case HALF_UP, will have this result:
2.4 = 2
2.5 = 3
2.7 = 3
You can check the RoundingMode
information here: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
Jason
Updated on August 08, 2022Comments
-
Jason almost 2 years
Why does the following code raise the exception shown below?
BigDecimal a = new BigDecimal("1.6"); BigDecimal b = new BigDecimal("9.2"); a.divide(b) // results in the following exception.
Exception:
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
-
shareef almost 10 yearsthis works for jasper error too thanks community.jaspersoft.com/questions/528968/…
-
Martin Serrano about 9 yearsin addition to the code, some explanation should be provided.
-
John Manko over 8 years
-
John Manko over 8 years
-
ACV over 7 yearsRoundingMode.HALF_EVEN is recommended for financial applications. This is what's used in banking
-
Stimpson Cat almost 6 yearsFor those, who are confused by John Mankos's comment on precision, please see this answer stackoverflow.com/questions/4591206/…
-
egemen over 5 years(new BigDecimal(100)).divide(new BigDecimal(0.90), 2,RoundingMode.HALF_UP)
-
user207421 about 4 years@AnandVarkeyPhilips It is the scale. See the Javadoc. Edit rejected.
-
user207421 about 4 years4 is the scale, not the precision.
-
Anand Varkey Philips about 4 years@user207421, I accidentally edited it and tried reverting.. But didnt have enough points to delete an edit.... meta.stackexchange.com/questions/80933/…
-
Satish Patro almost 4 yearsIf I want 2 decimal digit after, how to achieve using MatchContext?
-
siefca about 3 yearsCAUTION! The problem with just applying some rounding mode is that it also has effect on operations that would normally return a value having a finite number of decimal places. When rounding is used the result is scaled to the scale of a divident. For example: 1 / 8 will result in 0.125 but if you apply rounding it will be 1.
-
MarkHu over 2 yearsOmitting the
scale
parameter may yield undesirable results for some inputs. -
MarkHu over 2 yearsThe code from this example gave the same error as OP.