Contenuto principale

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 from the Polyspace Platform user interface, you can apply this option through the project configuration. To do so, navigate to the Static Analysis tab, select the Advanced node, and enter this option in the Other field. 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
PQL Name: std.defects.BAD_FLOAT_OP

Version History

Introduced in R2013b