Reputation: 736
What could be the reason for difference in floating point accuracy here?
def "emi test"(){
given:
def P = 6000000.00
def n = 20 * 12
def r = (8.35/12)/100
double emi_g = (P * r * (1+r).power(n)) / ((1+r).power(n) - 1)
double emi_j= (P * r * Math.pow(1+r,n)) / (Math.pow(1+r,n)-1);
expect:
emi_g == emi_j
}
result:
emi_g == emi_j
| | |
| | 51501.177737160346
| false
51501.177737160666
Upvotes: 0
Views: 108
Reputation: 27245
The issue is related to types.
(1 + r).power(n) - 1
evaluates to a BigDecimal
P * r * (1 + r).power(n)
evaluates to a BigDecimal
P * r * Math.pow(1 + r, n)
evaluates to a Double
Math.pow(1 + r, n) - 1
evaluates to a Double
It isn't clear what your requirements are and whether or not you care about the precision being lost and knowing those requirements would help describe how to get the desired behavior. The answer to the question as asked...
What could be the reason for difference in floating point accuracy here?
Is because the expressions evaluate to different types and the rules associated with dividing a Double
by a Double
(and the fact that you are the numerator and denominator values are in a Double
to begin with, as opposed to BigDecimial
) cause you to lose some precision.
Upvotes: 0
Reputation: 45329
The difference is explained by the data type of the results.
When run in a shell, the types of your results are:
groovy:000> emi_g.getClass()
===> class java.math.BigDecimal
groovy:000> emi_j.getClass()
===> class java.lang.Double
Groovy's implementation returns a BigDecimal
, which has better precision than Double
Upvotes: 2