Dev Tip: Do not Test for Equality

You almost never want to write code like the following:

double x;
double y;
...
if (x == y) {...}

Most floating point operations involve at least a tiny loss of precision. Even if two numbers are equal for all practical purposes, they may not be exactly equal down to the last bit, and so the equality test is likely to fail.

For example, the following code snippet prints -1.77635683940025E-15. Although in theory, squaring should undo a square root, the round-trip operation is slightly inaccurate.

double x = 10; 
double y = System.Math.Sqrt(x);
y *= y;
if (x == y)
  Rhino.RhinoApp.WriteLine("Square root is exact");
else
  Rhino.RhinoApp.WriteLine("{0}", x-y);

In most cases, the equality test above should be written as something like the following:

double tolerance = ...
if (System.Math.Abs(x - y) < tolerance) {...}

Here, tolerance is some threshold that defines what is close enough for equality. This begs the question of how close is close enough. This cannot be answered in the abstract; you have to know something about your particular problem to know how close is close enough in your context.

4 Likes

Thanks for the hint, Dale!

For the same reason one should never use floating point counters for loops. In particular while dealing with curve or surface domains. It will never hit the upper limit exactly - therefore you’ll miss the last point or it will be slightly too short.

And if you use RhinoCommon, you can use EpsilonEquals: http://4.rhino3d.com/5/rhinocommon/html/M_Rhino_RhinoMath_EpsilonEquals.htm

1 Like

I guess I should add that floating-point arithmetic isn’t tied to any particular language. So the above tip applies to RhinoScript, Rhino.Python, Visual Basic, and C++ (too).

1 Like

Loving the article. I faced something similar some weeks ago. It’s a very common error that comes from not considering floating point numbers real nature.

I should add that some floating points (as coordinates, plane axis components…) could be tested using some particular rhinocommon methods created to test some objects properties; so perhaps for some problems, you don’t need to deal with tolerances and floating point operations.

Thanks for posting and starting with this posts series about DevTips :slight_smile: