I'm facing an issue while trying to round up the decimal places in a number to the nearest hundered-thousandth digit.
Example :
BigDecimal num1 = BigDecimal.valueOf(0.38871551);
MathContext mc = new MathContext(5);
System.out.println(num1.round(mc));
The output is 0.38872 which is as expected. All good so far. Let's take another example :
BigDecimal num1 = BigDecimal.valueOf(1.1680418);
MathContext mc = new MathContext(5);
System.out.println(num1.round(mc));
The output is 1.1680. This is where the problem arrises. What I want is the output to be 1.16804 but the rounding seems to eat up the 4 instead of leaving it as it is.
I tried different rounding modes but this is what I get :
RoundMode.UP gives 1.1681
RoundingMode.HALF_UP or RoundingMode.HALF_DOWN give 1.1680
and so on..
How do I get the desired output :
0.38871551 should round to 0.38872
1.1680418 should round to 1.16804
0.55052984 should round to 0.55053
I even tried rounding to the 6th decimal place instead of the 5th but I'm not able to find the right combination that gives me the desired output as shown above.
You can try it with setScale Function of BigDecimal
num1 = num1.setScale(5, BigDecimal.ROUND_HALF_UP);
MathContext(int) rounds the number to that amount of digits, taking the whole number into account instead of just the digits after the comma.
say you use these numbers:
BigDecimal ten = BigDecimal.valueOf(10.55052984);
MathContext five = new MathContext(5);
MathContext two = new MathContext(2);
System.out.println(ten.round(five));
System.out.println(ten.round(two));
It will produce a number rounded to the 5th or 2nd digit, regardless of its position:
10.551
11
This should work:
BigDecimal num1 = BigDecimal.valueOf(0.38871551);
System.out.println(num1.setScale(5, RoundingMode.HALF_UP));
num1 = BigDecimal.valueOf(1.1680418);
System.out.println(num1.setScale(5, RoundingMode.HALF_UP));
num1 = BigDecimal.valueOf(0.55052984);
System.out.println(num1.setScale(5, RoundingMode.HALF_UP));
0.38872
1.16804
0.55053
you can try this way
DecimalFormat df = new DecimalFormat("#.00000");
System.out.print(df.format(1.1680418)); //1.16804
Related
In java code I have 1 input being :16275.874999999998
I build a method which rounds it up to: 16275.87
But the right answer is: 16275.88
How do I fix that in Java?
My current rounding method:
public static double round(final double value, final int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
Edit: I thought "the right answer" had .88 because the 9s would round up but that's not the case with the method I am using, will definitely look into rewrite it to consider previous decimal points.
Many thanks for the replies everyone!
Java is actually rounding your number correctly. Since you're rounding to 2 places, the setScale method looks at the third decimal spot which is 4 in your example. Since 4 < 5, your HALF_UP rounding mode will behave like ROUND_DOWN, which is why your output is 16275.87 instead of 16275.88
In order for your number to round up to 16275.88, you would need to run your method with input as round(round(16275.874999999998, 3), 2)
If you are looking to always round up then you need to use RoundingMode.CEILING or RoundingMode.UP (depending on how you want negative numbers to behave), instead of RoundingMode.HALF_UP
bd = bd.setScale(places, RoundingMode.CEILING);
HALF_UP will round up for anything with 5 or over in the first decimal place that is getting discarded and round down for anything less than 5 in that position.
CEILING and UP will always round up for positive numbers so 16275.871 will round to 16275.88. The difference between the two is how they handle negative numbers. CEILING rounds towards the positive numbers and UP will round towards the larger negative number.
CEILING of -16275.871 = -16275.871
UP of -16275.871 = -16275.88
I am new to the Java world and am trying to learn how to use BigDecimal. What I am trying to do now is limit the number of decimal places in a division problem. My line of code is:
quotient=one.divide(x);
Where quotient, one and x are all of type BigDecimal. I cannot figure out, however, how to limit the number of decimal places to print out, saying that x is some large number, and one is equal to 1. All help is appreciated, thanks!
That code will die a horrible death if the division has a non-terminating decimal expansion. See javadoc of divide(BigDecimal divisor):
if the exact quotient cannot be represented (because it has a non-terminating decimal expansion) an ArithmeticException is thrown.
Example:
BigDecimal one = BigDecimal.ONE;
BigDecimal x = BigDecimal.valueOf(7);
one.divide(x); // throws java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
Use one of the other overloads of divide(), e.g. divide(BigDecimal divisor, int scale, RoundingMode roundingMode):
BigDecimal one = BigDecimal.ONE;
BigDecimal x = BigDecimal.valueOf(7);
BigDecimal quotient = one.divide(x, 5, RoundingMode.HALF_UP);
System.out.println(quotient); // prints: 0.14286
BigDecimal one = BigDecimal.ONE;
BigDecimal x = BigDecimal.valueOf(7);
BigDecimal quotient = one.divide(x, 30, RoundingMode.HALF_UP);
System.out.println(quotient); // prints: 0.142857142857142857142857142857
To set the number of decimal places in a variable BigDecimal you can use the following sentences depend that you want achieve
value = value.setScale(2, RoundingMode.CEILING) to do 'cut' the part after 2 decimals
or
value = value.setScale(2, RoundingMode.HALF_UP) to do common round
See Rounding BigDecimal to *always* have two decimal places
I've got a problem with the result of division of BigDecimal instances.
My program:
public class DecimalPrecision
public static void main(String[] args) {
MathContext mathContext = new MathContext(25, RoundingMode.HALF_UP);
System.out.println(new BigDecimal("0.1111111111111111111111111").divide(new BigDecimal("3"), mathContext).toString());
}
The result is the following:
0.03703703703703703703703703
But the correct result is:
0.03703703703703703703703704
Basically my program rounded the last digit, which is 7, to 3, not to 4. Why is it so? In mathContext I specified rounding mode HALF_UP. Probably I've got a gap in knowlegde on the issue but I was sure that HALF_UP rounds to a bigger value.
This problem can be sorted out in the next way:
value1 = value1.divide(value2, 10000, RoundingMode.HALF_UP);
return new BigDecimal(value1.toString()).round(mathContext);
But in my taste there's something wrong with parsing the result to a String and then create new properly rounded BigDecimal. I'm asking for your help, how can I resolve this problem without resorting to any strings?
Thanks in advance.
You are starting with a 25 digit number and performing an operation with a precision of 25 digits so you can expect that the last digit might be wrong. The solution is to use more digits than you need and round the result.
BigDecimal oneNinth25 = BigDecimal.ONE.divide(BigDecimal.valueOf(9), 25, BigDecimal.ROUND_HALF_UP);
BigDecimal oneNinth26 = BigDecimal.ONE.divide(BigDecimal.valueOf(9), 26, BigDecimal.ROUND_HALF_UP);
MathContext mathContext = new MathContext(25, RoundingMode.HALF_UP);
System.out.println("1/9 to 25 digits / 3 = " +
oneNinth25.divide(BigDecimal.valueOf(3), mathContext));
System.out.println("1/9 to 26 digits / 3 = " +
oneNinth26.divide(BigDecimal.valueOf(3), mathContext));
prints
1/9 to 25 digits / 3 = 0.03703703703703703703703703
1/9 to 26 digits / 3 = 0.03703703703703703703703704
I'm trying to round a double to the nearest two decimal places however, it is just rounding to the nearest full number.
For example, 19634.0 instead of 19634.95.
This is the current code I use for the rounding
double area = Math.round(Math.PI*Radius()*Radius()*100)/100;
I can't see where i am going wrong.
Many thanks for any help.
Well, Math.round(Math.PI*Radius()*Radius()*100) is long. 100 is int.
So Math.round(Math.PI*Radius()*Radius()*100) / 100 will become long (19634).
Change it to Math.round(Math.PI*Radius()*Radius()*100) / 100.0. 100.0 is double, and the result will also be double (19634.95).
You can use a DecimalFormat object:
DecimalFormat df = new DecimalFormat ();
df.setMaximumFractionDigits (2);
df.setMinimumFractionDigits (2);
System.out.println (df.format (19634.95));
Do you actually want want to round the value to 2 places, which will cause snowballing rounding errors in your code, or simply display the number with 2 decimal places? Check out String.format(). Complex but very powerful.
You might want to take a look at the DecimalFormat class.
double x = 4.654;
DecimalFormat twoDigitFormat = new DecimalFormat("#.00");
System.out.println("x=" + twoDigitFormat.format());
This gives "x=4.65". The difference between # and 0 in the pattern is that the zeros are always displayed and # will not if the last ones are 0.
The following example came from this forum, but seems to be what you are looking for.
double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
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)