Main Content

Floating point comparison with equality operators

Imprecise comparison of floating-point variables

Description

This defect occurs when you use an equality (==) or inequality (!=) operation with floating-point numbers.

Polyspace® does not raise a defect for an equality or inequality operation with floating-point numbers when:

  • The comparison is between two float constants.

        float flt = 1.0;
        if (flt == 1.1)
  • The comparison is between a constant and a variable that can take a finite, reasonably small number of values.

    float x;
    
    int rand = random(); 
    switch(rand) { 
    case 1: x = 0.0; break; 
    case 2: x = 1.3; break; 
    case 3: x = 1.7; break; 
    case 4: x = 2.0; break; 
    default: x = 3.5; break; }
    …
    if (x==1.3) 
  • The comparison is between floating-point expressions that contain only integer values.

    float x = 0.0;
    for (x=0.0;x!=100.0;x+=1.0) {
    …
    if (random) break;
    }
    
    if (3*x+4==2*x-1)
    …
    if (3*x+4 == 1.3)
  • One of the operands is 0.0, unless you use the option flag -detect-bad-float-op-on-zero.

    /* Defect detected when
    you use the option flag */
    
    if (x==0.0f) 

    If you are running an analysis through the user interface, you can enter this option in the Other field, under the Advanced Settings node on the Configuration pane. See Other.

    At the command line, add the flag to your analysis command.

    polyspace-bug-finder -sources filename ^
    -checkers BAD_FLOAT_OP -detect-bad-float-op-on-zero

Risk

Checking for equality or inequality of two floating-point values might return unexpected results because floating-point representations are inexact and involve rounding errors.

Fix

Instead of checking for equality of floating-point values:

if (val1 == val2)
check if their difference is less than a predefined tolerance value (for instance, the value FLT_EPSILON defined in float.h):
#include <float.h>
if(fabs(val1-val2) < FLT_EPSILON)

See examples of fixes below.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Examples

expand all

#include <stdio.h>
#include <math.h>
#include <float.h>

void func(void)
{
    float f;
    for (f = 1.0; f != 2.0; f = f + 0.1)    
        (void)printf("Value: %f\n", f);
}

In this function, the for-loop tests the inequality of f and the number 2.0 as a stopping mechanism. The number of iterations is difficult to determine, or might be infinite, because of the imprecision in floating-point representation.

Correction — Change the Operator

One possible correction is to use a different operator that is not as strict. For example, an inequality like >= or <=.

#include <stdio.h>
#include <math.h>
#include <float.h>

void func(void)
{
    float f;
    for (f = 1.0; f <= 2.0; f = f + 0.1)    
        (void)printf("Value: %f\n", f);
}

Result Information

Group: Programming
Language: C | C++
Default: Off
Command-Line Syntax: BAD_FLOAT_OP
Impact: Medium

Version History

Introduced in R2013b