Skip to content

Gendarme.Rules.Correctness.AvoidFloatingPointEqualityRule(2.10)

Sebastien Pouliot edited this page Feb 9, 2011 · 3 revisions

AvoidFloatingPointEqualityRule

Assembly: Gendarme.Rules.Correctness
Version: 2.10

Description

In general floating point numbers cannot be usefully compared using the equality and inequality operators. This is because floating point numbers are inexact and most floating point operations introduce errors which can accumulate if multiple operations are performed. This rule will fire if [in]equality comparisons are used with Single or Double types. In general such comparisons should be done with some sort of epsilon test instead of a simple compare (see the code below). For more information:

  • [http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm Floating Point Comparison (General Problem)]
  • [http://www.yoda.arachsys.com/csharp/floatingpoint.html Another article about floating point comparison (more .NET adapted)]

Examples

Bad example:

// This may or may not work as expected. In particular, if the values are from
// high precision real world measurements or different algorithmic sources then
// it's likely that they will have small errors and an exact inequality test will not
// work as expected.
public static bool NearlyEqual (double [] lhs, double [] rhs)
{
    if (ReferenceEquals (lhs, rhs)) {
        return true;
    }
    if (lhs.Length != rhs.Length) {
        return false;
    }
    for (int i = 0; i < lhs.Length; ++i) {
        if (lhs [i] != rhs [i]) {
            return false;
        }
    }
    return true;
}

Good example:

// This will normally work fine. However it will not work with infinity (because
// infinity - infinity is a NAN). It's also difficult to use if the values may
// have very large or very small magnitudes (because the epsilon value must
// be scaled accordingly).
public static bool NearlyEqual (double [] lhs, double [] rhs, double epsilon)
{
    if (ReferenceEquals (lhs, rhs)) {
        return true;
    }
    if (lhs.Length != rhs.Length) {
        return false;
    }
    for (int i = 0; i < lhs.Length; ++i) {
        if (Math.Abs (lhs [i] - rhs [i]) > epsilon) {
            return false;
        }
    }
    return true;
}

Notes

  • Prior to Gendarme 2.2 this rule was named FloatComparisonRule.
Clone this wiki locally