Recovering from Divide By 0 and Coming Back From Infinity with IsNaN and IsInfinite
While doing a series of regression tests, I noticed a few tests displayed errors due to a returned result of NaN. When I checked the test itself, it was for a margin calculation, and in some cases, one of the values was zero. This caused a divide by zero error, which returns NaN as a result. If this happens on the site, a 0.0% is displayed, but my test didn’t handle it correctly.
There would be two ways to approach this. One is the detect zeros before doing a divide and set the result to 0. This forces the result to agree with the site.
Another method is to use the isNaN function of Groovy. The calculation code stays the same, but the result is checked to see if it’s a number. For my situation, if the results is NaN, I set the answer to 0.0 to match the site result.
My formula is the following:
float calculatedMargin=(((Float.valueOf(GP) / Float.valueOf(sales)) * 100).round(1))
While it wouldn’t be hard to check if the value of GP or Sales is 0, I prefer to check the result at the end of the calculation using the following:
//If the result is NaN, or Infinity, set the calculatedMargin value to 0.0
if (calculatedMargin.isNaN()==true){ calculatedMargin=0.0 } if (calculatedMargin.isInfinite()==true){ calculatedMargin=0.0 }
You’ll notice there is an isInfinite check. After correcting the NaN issue, I noticed the calculation could also return “Infinity” as a result. This is basically the other side of the coin when doing calculations with zero. If detected, this check sets the calculatedMargin to zero.
Both of these division errors are now handled by built in functions. Again, I could try and prevent the error in the first place by checking for zero values before doing any calculations. But, I prefer the second approach and just check the result. I could turn this validation into a Keyword, pass the calculated result, and use the validation in multiple places. That might be more efficient way of detecting and controlling the error.
I saw many solutions to this problem, but Groovy has these built in functions that handle the situation nicely and my false positive errors have been handled.