S1244 — Floating point numbers should not be tested for equality

Language
C#
Type
Bug
Severity
Major

Why is this an issue?

Floating point numbers in C# (and in most other programming languages) are not precise. They are a binary approximation of the actual value. This means that even if two floating point numbers appear to be equal, they might not be due to the tiny differences in their binary representation.

Even simple floating point assignments are not simple:


float f = 0.100000001f; // 0.1
double d = 0.10000000000000001; // 0.1

(Note: Results may vary based on the compiler and its settings)

This issue is further compounded by the non-associative nature of floating point arithmetic. The order in which operations are performed can affect the outcome due to the rounding that occurs at each step. Consequently, the outcome of a series of mathematical operations can vary based on the order of operations.

As a result, comparing float or double values for exact equality is typically a mistake, as it can lead to unexpected behavior. This applies whether the comparison uses the equality (==) or inequality (!=) operators or the Equals method.

How to fix it

Consider using a small tolerance value to check if the numbers are "close enough" to be considered equal. This tolerance value, often called epsilon, should be chosen based on the specifics of your program.

Code examples

Noncompliant code example


float myNumber = 3.146f;

if (myNumber == 3.146f) // Noncompliant: due to floating point imprecision, this will likely be false
{
  // ...
}

if (myNumber < 4 || myNumber > 4) // Noncompliant: indirect inequality test
{
  // ...
}

Compliant solution


float myNumber = 3.146f;
float epsilon = 0.0001f; // or some other small value

if (Math.Abs(myNumber - 3.146f) < epsilon)
{
  // ...
}

if (myNumber <= 4 - epsilon || myNumber >= 4 + epsilon)
{
  // ...
}

The Equals method has the same problem and should be handled the same way:

Noncompliant code example


float myNumber = 3.146f;

if (myNumber.Equals(3.146f)) // Noncompliant: due to floating point imprecision, this will likely be false
{
  // ...
}

Compliant solution


float myNumber = 3.146f;
float epsilon = 0.0001f; // or some other small value

if (Math.Abs(myNumber - 3.146f) < epsilon)
{
  // ...
}

Resources

Documentation

↑ Back to top