A Generic Floating Point Comparison Class

You should never compare floating point values for equality using the following operators:

  • ==
  • <=
  • >=
float a = 2.0f;
float b = a;

// any of these is best avoided

if(a == b) {
    // you expect it to work but sometimes it won't
}

if(a <= b) {     
    // you expect it to work but sometimes it won't 
} 

if(a >= b) {
    // you expect it to work but sometimes it won't
}

Why? The short answer is because the representation of floating numbers is not consistent such that two floats may have the same perceived value but differ in bit representation. The long answer is here.

So how do we compare floats for equality then? If you’re using Unity, Mathf.Approximately() is very handy. Here’s a full Comparison class using exactly that:

using UnityEngine;

/**
 * Class for comparing floating point values 
 */
public static class Comparison {

    /**
     * Returns whether or not a == b
     */
    public static bool TolerantEquals(float a, float b) {
        return Mathf.Approximately(a, b);
    }

    /**
     * Returns whether or not a >= b
     */
    public static bool TolerantGreaterThanOrEquals(float a, float b) {
        return a > b || TolerantEquals(a, b);
    }

    /**
     * Returns whether or not a <= b
     */
    public static bool TolerantLesserThanOrEquals(float a, float b) {
        return a < b || TolerantEquals(a, b);
    }

}

If you’re not using Unity, you should define a tolerance value such that any value less then this is considered meaningless. This may vary across different games and applications. To define equality, we just take the absolute value of the difference of the two floating values and compare if this is lesser than the tolerance value. If it is, we can say that the two floating values are equal. In other words, we are merely discarding floating values that are already too small to be significant for our use.

using System;

/**
 * Class for comparing floating point values 
 */
public static class Comparison {

    private const float TOLERANCE_VALUE = 0.0001f;

    /**
     * Returns whether or not a == b
     */
    public static bool TolerantEquals(float a, float b) {
        return Math.Abs(a - b) < TOLERANCE_VALUE;
    }

    /**
     * Returns whether or not a >= b
     */
    public static bool TolerantGreaterThanOrEquals(float a, float b) {
        return a > b || TolerantEquals(a, b);
    }

    /**
     * Returns whether or not a <= b
     */
    public static bool TolerantLesserThanOrEquals(float a, float b) {
        return a < b || TolerantEquals(a, b);
    }

}

Finally, the following are the sample usage:

float a = 2.0f;
float b = a;

// these are better

if(Comparison.TolerantEquals(a, b)) {
    // now this works as expected
}

if(Comparison.TolerantLesserThanOrEquals(a, b)) {     
    // now this works as expected
} 

if(Comparison.TolerantGreaterThanOrEquals(a, b)) {
    // now this works as expected
}

Now look at your code and see if you’re making this mistake. This may be the source of bugs that you couldn’t solve before.

Advertisements

One thought on “A Generic Floating Point Comparison Class

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s