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.)

Jongware
  • 22,200
  • 8
  • 54
  • 100
Wizmann
  • 839
  • 1
  • 9
  • 14
  • 1
    What is the difference between bitwise and by value? Surely they are the same for floats – Ed Heal May 06 '15 at 03:52
  • @EdHeal all right, the problem is edited – Wizmann May 06 '15 at 03:54
  • 5
    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 ...**](http://floating-point-gui.de/) – David C. Rankin May 06 '15 at 03:55
  • 1
    @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 :-) – user2864740 May 06 '15 at 03:58
  • 2
    I stand corrected. Thanks for pointing those cases out. – David C. Rankin May 06 '15 at 04:00
  • Is +0 == -1? Also is doing equality with floats a good idea? – Ed Heal May 06 '15 at 04:04
  • 3
    @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. – Jon Purdy May 06 '15 at 04:13

3 Answers3

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
Nayuki
  • 17,911
  • 6
  • 53
  • 80
  • 3
    ...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). – Jerry Coffin May 06 '15 at 04:05
  • 1
    C++ doesn't require IEEE754 (although [there is a static variable you can check to see if ieee754 is in use](http://stackoverflow.com/questions/5777484/how-to-check-if-c-compiler-uses-ieee-754-floating-point-standard)). – M.M May 06 '15 at 04:05
3

gcc and clang use the UCOMISS x86/x64 instruction.

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

M.M
  • 138,810
  • 21
  • 208
  • 365
  • 5
    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. – Jon Purdy May 06 '15 at 04:03
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.

Ivan Ling
  • 127
  • 2
  • 10