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.
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 no MathContext 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.
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'.
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 :
http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=java6&state=class&package=java.math&class=MathContext
To fix such an issue I have used the below code
a.divide(b, 2, RoundingMode.HALF_EVEN)
Where 2 is scale. Now the problem should be resolved.
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/
It´s a issue of rounding the result, the solution for me is the following.
divider.divide(dividend,RoundingMode.HALF_UP);
Answer for BigDecimal throws ArithmeticException
public static void main(String[] args) {
int age = 30;
BigDecimal retireMentFund = new BigDecimal("10000.00");
retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal yearsInRetirement = new BigDecimal("20.00");
String name = " Dennis";
for ( int i = age; i <=65; i++){
recalculate(retireMentFund,new BigDecimal("0.10"));
}
BigDecimal monthlyPension = retireMentFund.divide(
yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));
System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
}
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
fundAmount.multiply(rate.add(new BigDecimal("1.00")));
}
Add MathContext object in your divide method call and adjust precision and rounding mode. This should fix your problem
Your program does not know what precision for decimal numbers to use so it throws:
java.lang.ArithmeticException: Non-terminating decimal expansion
Solution to bypass exception:
MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17
For me, it's working with this:
BigDecimal a = new BigDecimal("9999999999.6666",precision);
BigDecimal b = new BigDecimal("21",precision);
a.divideToIntegralValue(b).setScale(2)
This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I am building a program that calculates the total cost of a restaurant bill. My program is rounding $18.135 down to $18.13. This is the code that I am using to round it to two decimal places:
tip = Math.round((charge * TIP_PERCENTAGE) * 100) / 100d;
All of the variables are doubles, and charge is equal to 100.75 and TIP_PERCENTAGE is equal to 0.18.
I tried a couple of things but I have not had any luck. I want the program to round $18.135 up to $18.14.
Try this
private static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(Double.toString(value));
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
...
tip =(charge * TIP_PERCENTAGE) ;
tip = round(tip,2);
This question already has answers here:
Why not use Double or Float to represent currency?
(16 answers)
Closed 5 years ago.
Following is my code to convert long (cents) to dollar, however, there is 1 cent difference.
My expected answer is: $123,456,789,123,456.47, but the output is $123,456,789,123,456.48
public static void main(String[] args) {
long l = 12345678912345647L;
double d = l / 100.00;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
System.out.println(formatter.format(d));
}
For numbers greater than ~70 trillion BigDecimal should be used to remain accurate.
public static void main(String[] args) {
BigDecimal l = new BigDecimal("12345678912345647");
BigDecimal d = l.divide(new BigDecimal("100.00"));
NumberFormat formatter = NumberFormat.getCurrencyInstance();
System.out.println(formatter.format(d));
}
It is rounding like that because you are getting the output of a long divided by a number to 2 decimal places and then it's being stored in the double. If you want to get the number without it being rounded up try dividing by 100.000 or by replacing the long l with double l.
This question already has answers here:
ArithmeticException: "Non-terminating decimal expansion; no exact representable decimal result"
(9 answers)
Closed 7 years ago.
I'm conducting an experiment in which we will occasionally have to divide small numbers by large numbers, for example: 4 / 90,000. Using a double results in a 4.444444444e. I was hoping perhaps a BigDecimal could handle this arithmetic and give me a meaningful decimal, but my implementation throws an error:
int count = 4;
int total = 90,000;
er = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(total));
Error is:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1616)
Update: I am interesting in atleast 3 decimal places of precision.
You could pass a MathContext to the division method call. Something like,
int count = 4;
int total = 90000;
BigDecimal er = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(total),
MathContext.DECIMAL128);
System.out.println(er);
And I get
0.00004444444444444444444444444444444444
Let's look at the following code snippet in Java.
package division;
import java.math.BigDecimal;
final public class Main
{
public static void main(String[] args)
{
BigDecimal a = new BigDecimal(2);
BigDecimal b = new BigDecimal(3);
System.out.println(a.multiply(b));
System.out.println(a.add(b));
System.out.println(b.subtract(a));
System.out.println(a.divide(b));
}
}
In the above code snippet, all of the operations except the last one (division) are performed successfully. An attempt to divide two BigDecimal numbers in Java throws the java.lang.ArithmeticException. Why? What is the solution to this problem?
From the BigDecimal#divide(BigDecimal) documentation:
...if the exact quotient cannot be represented (because it has a non-terminating decimal expansion) an ArithmeticException is thrown.
In your specific case "2/3" has a non-terminating decimal expansion (0.6666...) so you'll have to use a form of divide() which takes a scale and/or RoundingMode to resolve the infinite representation. For example:
BigDecimal a = new BigDecimal(2);
BigDecimal b = new BigDecimal(3);
a.divide(b, 4, RoundingMode.CEILING); // => 0.6667
a.divide(b, 4, RoundingMode.FLOOR); // => 0.6666
You get the exception because there is no exact representation of the result of the division. In order to work around this problem, you need to use the overload with the scale and rounding mode, like this:
System.out.println(a.divide(b, 20, RoundingMode.HALF_UP));
Here is your modified code on ideone.
6
5
1
0.66666666666666666667
If you read the javadoc it says it will throw an java.lang.ArithmeticException if the exact quotient does not have a terminating decimal expansion. 2/3 = .666666666... and does not terminate
Returns a BigDecimal whose value is (this / divisor), and whose preferred scale is (this.scale() - divisor.scale()); if the exact quotient cannot be represented (because it has a non-terminating decimal expansion) an ArithmeticException is thrown.
2 / 3 = 0.666666666666666666666........ and so on, and it cannot be represented. As JavaDoc says, it's a non-terminating decimal expansion