I was using BigDecimal, but I am still getting different results for two different (mathematically identical) expressions:
First Expression: PI - (10^(-14)/PI)
Second Expression: (PI^2 - 10^(-14))/PI
To put it more simply, here is the equation:
package set1;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class FloatingLaws {
final static BigDecimal PI = BigDecimal.valueOf(Math.PI);
public static void main(String[] args) {
System.out.println(firstExpression());
System.out.println(secondExpression());
}
private static BigDecimal secondExpression() {
return PI.subtract((BigDecimal.valueOf(Math.pow(10, -14)).divide(PI,50,RoundingMode.CEILING)));
}
private static BigDecimal firstExpression() {
return (PI.multiply(PI).subtract(BigDecimal.valueOf(Math.pow(10, -14)))).divide(PI, 50,RoundingMode.CEILING);
}
}
After executing this code, no matter how big is rounding, last digit is always different. In my case I get these two results:
3.14159265358978981690113816209304300915191180404867
3.14159265358978981690113816209304300915191180404866
My question is why is this happening and is it solvable?
It is because You are doing this:
pi - ((10^-4)/pi)
<- only the part in bracket is ceiled,
which is different from
((pi^2-10^-14)/pi)
<- where the whole expression is ceiled.
You use BigDecimal and you have rounding mode CEILING with precision 50. In both of your expressions the ceiling is applied when you divide by PI number. So if you divide by PI eager like in first expression, then you could get less accurate results - because you CEIL intermediate value, before your formula fully execute, so you loose the CEILED part from the divide by PI operation and this in further computation creates the "error" effect. When you divide by PI last, like in second expression, you use more accurate formula, which is ceiling only the result, not intermediate value like in first expression, so it calculates more preciselly, rounding only the result and not intermediate value.