Tarvo Mäesepp Tarvo Mäesepp - 3 months ago 30
Swift Question

Calculating rating gives "NaN"

I tried to calculate rating with values from Firebase. However the output is always "nan"(“not a number”) whatever what those "ratersCount" and "rating" values are. What could cause this and how to fix it?

This is how I get values from Firebase:

let ref = FIRDatabase.database().reference().child("Snuses").queryOrdered(byChild: "Brand").queryEqual(toValue: brandName)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists(){

let enumerator = snapshot.children

while let thisProduct = enumerator.nextObject() as? FIRDataSnapshot

// Chances are you'd have to create a dictionary
let thisProductDict = thisProduct.value as! [String:AnyObject]
let rating = thisProductDict["rating"] as! Double
let ratersCount = thisProductDict["ratersCount"] as! Double

let ratingToShow: Double = rating / ratersCount//Here I do the calculation

If I try to print out rating, ratersCount and the calculations, the output is:

Rating is equal to nan

But I know the values are not even zero:

Catch Dry Eucalyptus White Mini
ratersCount: 2
rating: 5


With floating point arithmetics (decimals) dividing by zero (which is an invalid operation) returns a special error value NaN (Not a Number).

The fix is very simple, you have to check for zero first:

// return zero if ratesCount is zero
let ratingToShow = (ratersCount == 0) ? 0 : rating / ratersCount

Note that if you had two integers there (e.g. Int type), the division would result in a crash.

A safer code would be to merge the check with check for nil:

let ratingToShow: Double

if let rating = thisProductDict["rating"] as? Double,
    let ratersCount = thisProductDict["ratersCount"] as? Double,
    ratersCount > 0 {

    ratingToShow = rating / ratersCount
} else {
   ratingToShow = 0

To prevent crash with invalid data if you are worried about that.