How do C and C++ compilers implement the decision of equality for float numbers?
Asked Answered
F

3

7

For example,

float a = 1.0;
float b = 1.2;

puts(a == b? "equal": "not equal");

Does compiler deal with it bitwisely or by some other methods?

(I know it's not a good choice to decide the equality of floating-point numbers by "==", I just want to know how a compiler deals with this situation.)

Formation answered 6/5, 2015 at 3:46 Comment(7)
What is the difference between bitwise and by value? Surely they are the same for floatsBradberry
@EdHeal all right, the problem is editedFormation
All floating point numbers are stored in IEEE-754 Floating Point Format. They are either 32-bit (single precision floating point) or 64-bit (double precision floating point). Meaning there is an integer equivalent for every floating point number based on the bits in memory. The compiler handles it the same way it does an integer of equivalent size. See: The Floating-Point Guide - What Every Programmer Should Know ...Soler
@DavidC.Rankin With the exception of +0/-0 (distinct bit patterns) anyway .. and NaNs being unordable. That is, there is a special case of different bitwise patterns that are equal, and some identical bitwise patterns which are not equal.. but good link :-)Williams
I stand corrected. Thanks for pointing those cases out.Soler
Is +0 == -1? Also is doing equality with floats a good idea?Bradberry
@EdHeal: +0 = −0. Neither is equal to −1. Equality on floats is precisely defined, it just produces results that are frequently surprising to newcomers. Basically it’s not a good idea unless you know what you’re doing. 1.0 + 1.0 == 2.0 always holds; 1.0/2.0 - 1.0/4.0 == 1.0/4.0 does too; 1.0/3.0 + 1.0/3.0 == 2.0/3.0 does not.Complaisance
O
5

The general, full answer is that floating-point numbers are compared according to the IEEE 754 specification.

To answer your question specifically, most of the time two floating-point numbers are compared bitwise, with a few exceptional cases:

  • Positive and negative zero are considered equal
  • NaN is considered unequal to everything, even to NaN itself
  • Subnormals may compare equal to zero and other subnormals in certain operating modes (e.g. "flush subnormals to zero")
  • Other than these exceptions, regular bitwise comparison is used
Odelia answered 6/5, 2015 at 4:3 Comment(2)
...except, of course, when the system doesn't use IEEE floating point (e.g., some IBM mainframes still don't, quite a few GPUs don't, at least usually).Dominik
C++ doesn't require IEEE754 (although there is a static variable you can check to see if ieee754 is in use).Glyconeogenesis
G
3

gcc and clang use the UCOMISS x86/x64 instruction.

Source: tried it with -O3 and inspected the assembly output.

Glyconeogenesis answered 6/5, 2015 at 3:58 Comment(1)
More generally, the compiler produces an architecture-specific instruction for comparing floating-point numbers if the architecture has hardware support for them—such as x86, x86-64, and ARM—otherwise it emits a sequence of instructions that implement the behaviour required by the floating-point standard in use, almost always IEEE-754.Complaisance
D
1

I'm assuming you mean after the program is compiled, how does it compare two floats. The way floats are stored is very unique. It is stored by sign, exponent and fraction as seen here. Therefore, unless it is absolutly equal, the program will see even 1 and 1.000000000001 as different. To check if they are almost equal, you can use the following:

bool AlmostEqualRelativeOrAbsolute(float A, float B,
            float maxRelativeError, float maxAbsoluteError)
{
    if (fabs(A - B) < maxAbsoluteError)
        return true;
    float relativeError;
    if (fabs(B) > fabs(A))
        relativeError = fabs((A - B) / B);
    else
        relativeError = fabs((A - B) / A);
    if (relativeError <= maxRelativeError)
        return true;
    return false;
}

The code is obtained from here, you may want to read more at the site.

Demonstrator answered 6/5, 2015 at 3:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.