comparing floating point numbers

Discussion in 'C++' started by Adam Majewski, Jan 29, 2012.

  1. Hi,

    I have seen code that compers like that :

    if (b == 0.0 && (a == 0.25 || a == -0.75))

    so I have checked it :

    #include <iostream>

    using namespace std;

    int main() {
    cout << boolalpha
    << "The true expression 0.25 == 0.25000000000000001 yields : "
    << (0.25 == 0.25000000000000001) << endl
    << "The false expression 0.25 == 0.2500000000000001 yields: "
    << (0.25 == 0.2500000000000001) << endl;
    }


    Is it operator overloadin ? Is it good code ?

    TIA

    Adam
     
    Adam Majewski, Jan 29, 2012
    #1
    1. Advertising

  2. Adam Majewski

    BCFD36 Guest

    On 1/29/12 10:48 AM, Adam Majewski wrote:
    > Hi,
    >
    > I have seen code that compers like that :
    >
    > if (b == 0.0 && (a == 0.25 || a == -0.75))
    >
    > so I have checked it :
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > int main() {
    > cout << boolalpha
    > << "The true expression 0.25 == 0.25000000000000001 yields : "
    > << (0.25 == 0.25000000000000001) << endl
    > << "The false expression 0.25 == 0.2500000000000001 yields: "
    > << (0.25 == 0.2500000000000001) << endl;
    > }
    >
    >
    > Is it operator overloadin ? Is it good code ?
    >
    > TIA
    >
    > Adam



    So what was the output from the code? I would think you might get
    different answers with different compilers.

    --
    Dave Scruggs
     
    BCFD36, Jan 29, 2012
    #2
    1. Advertising

  3. Adam Majewski

    MikeWhy Guest

    "BCFD36" <> wrote in message
    news:jg4540$n0$...
    > On 1/29/12 10:48 AM, Adam Majewski wrote:
    >> Hi,
    >>
    >> I have seen code that compers like that :
    >>
    >> if (b == 0.0 && (a == 0.25 || a == -0.75))
    >>
    >> so I have checked it :
    >>
    >> #include <iostream>
    >>
    >> using namespace std;
    >>
    >> int main() {
    >> cout << boolalpha
    >> << "The true expression 0.25 == 0.25000000000000001 yields : "
    >> << (0.25 == 0.25000000000000001) << endl
    >> << "The false expression 0.25 == 0.2500000000000001 yields: "
    >> << (0.25 == 0.2500000000000001) << endl;
    >> }
    >>
    >>
    >> Is it operator overloadin ? Is it good code ?
    >>
    >> TIA
    >>
    >> Adam

    >
    >
    > So what was the output from the code? I would think you might get
    > different answers with different compilers.


    The representation of a double precision floating point is standardized. It
    has 53 bits of mantissa, roughly 16 decimal digits of precision.
     
    MikeWhy, Jan 29, 2012
    #3
  4. On 29.01.2012 20:25, MikeWhy wrote:
    >
    > "BCFD36" <> wrote in message
    > news:jg4540$n0$...
    >> On 1/29/12 10:48 AM, Adam Majewski wrote:
    >>> Hi,
    >>>
    >>> I have seen code that compers like that :
    >>>
    >>> if (b == 0.0 && (a == 0.25 || a == -0.75))
    >>>
    >>> so I have checked it :
    >>>
    >>> #include <iostream>
    >>>
    >>> using namespace std;
    >>>
    >>> int main() {
    >>> cout << boolalpha
    >>> << "The true expression 0.25 == 0.25000000000000001 yields : "
    >>> << (0.25 == 0.25000000000000001) << endl
    >>> << "The false expression 0.25 == 0.2500000000000001 yields: "
    >>> << (0.25 == 0.2500000000000001) << endl;
    >>> }
    >>>
    >>>
    >>> Is it operator overloadin ? Is it good code ?
    >>>
    >>> TIA
    >>>
    >>> Adam

    >>
    >>
    >> So what was the output from the code? I would think you might get
    >> different answers with different compilers.

    >
    > The representation of a double precision floating point is standardized.
    > It has 53 bits of mantissa, roughly 16 decimal digits of precision.


    Sorry, no. While there are standards for floating point representation,
    and in particular the one you're referring (namely IEEE 754), how
    floating point values are represented with a given C++ compiler depends
    formally on the compiler, and in practice on the API for the OS that the
    compiler targets. std::numeric_limits<double>::iec something something
    tells you whether IEEE *representation* is used. It was meant to also
    tell you whether the compiler adheres to that standard. Unfortunately,
    in practice it only tells you about the representation.

    Cheers & hth.,

    - Alf
     
    Alf P. Steinbach, Jan 29, 2012
    #4
  5. On 29.01.2012 19:48, Adam Majewski wrote:
    > I have seen code that compers like that :
    >
    > if (b == 0.0 && (a == 0.25 || a == -0.75))


    Comparing floating point numbers for equality is almost always a bug.
    Only singular values like 0.0 are usually safe.


    Marcel
     
    Marcel Müller, Jan 29, 2012
    #5
  6. Adam Majewski

    BCFD36 Guest

    On 1/29/12 12:34 PM, Marcel Müller wrote:
    > On 29.01.2012 19:48, Adam Majewski wrote:
    >> I have seen code that compers like that :
    >>
    >> if (b == 0.0 && (a == 0.25 || a == -0.75))

    >
    > Comparing floating point numbers for equality is almost always a bug.
    > Only singular values like 0.0 are usually safe.
    >
    >
    > Marcel


    Agreed. And anyone who made it past the 1st Intro to CS class would know
    that. I've no idea of the Original Poster's background so I wasn't going
    to speculate on his training. I'm pretty sure english is a 2nd language
    for him so what he asked and what he meant to ask were not quite the
    same. I can't fault someone for that.

    But, yes, comparing floats for equality is not a good thing.

    --
    Dave Scruggs
     
    BCFD36, Jan 29, 2012
    #6
  7. Adam Majewski

    LR Guest

    Adam Majewski wrote:

    > I have seen code that compers like that :
    >
    > if (b == 0.0 && (a == 0.25 || a == -0.75))



    I suggest these two articles in the FAQ
    http://www.parashift.com/c -faq-lite/index.html

    [29.16] Why is floating point so inaccurate? Why doesn't this print 0.43?
    http://www.parashift.com/c -faq-lite/newbie.html#faq-29.16

    Perhaps more relevant to your question and with some interesting references.
    [29.17] Why doesn't my floating-point comparison work?
    http://www.parashift.com/c -faq-lite/newbie.html#faq-29.17
     
    LR, Jan 29, 2012
    #7
  8. Adam Majewski

    Miles Bader Guest

    BCFD36 <> writes:
    >>> if (b == 0.0 && (a == 0.25 || a == -0.75))

    >>
    >> Comparing floating point numbers for equality is almost always a bug.
    >> Only singular values like 0.0 are usually safe.

    >
    > Agreed. And anyone who made it past the 1st Intro to CS class would
    > know that. I've no idea of the Original Poster's background so I
    > wasn't going to speculate on his training. I'm pretty sure english is
    > a 2nd language for him so what he asked and what he meant to ask were
    > not quite the same. I can't fault someone for that.
    >
    > But, yes, comparing floats for equality is not a good thing.


    .... unless checking for the aforementioned "singular values", resulting
    from simple assignment rather than calculation, and known to have a
    representation that cannot suffer from precision loss etc.

    The latter _is_ perfectly fine, which is why, for instance, a simplistic
    compiler warning to complain about floating-point equality comparison
    isn't so useful...

    -miles

    --
    Brain, n. An apparatus with which we think we think.
     
    Miles Bader, Jan 30, 2012
    #8
  9. On Jan 29, 6:48 pm, Adam Majewski <> wrote:

    > I have seen code that compers like that :
    >
    > if (b == 0.0  && (a == 0.25 || a == -0.75))


    in general not very good. Though other posters have pointed out that
    these are rather special values.

    > so I have checked it :
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > int main() {
    >     cout  << boolalpha


    where is boolalpha declared? Is it part of iostream?

    >           << "The true expression  0.25 == 0.25000000000000001 yields : "
    >           << (0.25 ==                      0.25000000000000001) << endl
    >           << "The false expression 0.25 == 0.2500000000000001 yields: "
    >           << (0.25 ==                      0.2500000000000001) << endl;


    what do you expect this to give as a result?

    > }
    >
    > Is it operator overloadin ?


    no. Why would it be?

    > Is it good code ?


    no. don't think so but then I'm not sure what you're trying to show
     
    Nick Keighley, Jan 30, 2012
    #9
  10. Miles Bader <> wrote:
    > The latter _is_ perfectly fine, which is why, for instance, a simplistic
    > compiler warning to complain about floating-point equality comparison
    > isn't so useful...


    There are situations where you actually might want to make a ==
    comparison instead of anything else. One such example that I have
    personal experience about is when implementing a class that is a
    wrapper around a multiple-precision floating point library. In this
    particular case, I had an optimization that if the object is
    initialized with the exact value of 0.0 or 1.0 (in their double
    versions of the constructors/assignment), then it will use cached
    data instead of allocating new data. In this case comparing with ==
    is quite crucial, because if the given value differs from those even
    by the tiniest amount, using the cached data would be wrong. However,
    it's quite usual to initialize such values with 0.0 or 1.0.

    If, however, you want to make a ranged comparison to account for
    rounding errors, the vast majority of even experienced programmers
    don't realize how difficult that task actually is. Whatever your
    solution, it will not work properly in all possible cases. (The most
    naive solution of "fabs(a-b) < epsilon" is problematic because the
    precision of the comparison depends on the magnitude of the values:
    Larger values will be compared with a significantly stricter precision,
    ie. less rounding error is allowed, than values closer to zero.)

    I have written an article about this problem:

    http://warp.povusers.org/programming/floating_point_caveats.html
     
    Juha Nieminen, Jan 30, 2012
    #10
  11. On 29.01.2012 20:02, BCFD36 wrote:
    > On 1/29/12 10:48 AM, Adam Majewski wrote:
    >> Hi,
    >>
    >> I have seen code that compers like that :
    >>
    >> if (b == 0.0 && (a == 0.25 || a == -0.75))
    >>
    >> so I have checked it :
    >>
    >> #include <iostream>
    >>
    >> using namespace std;
    >>
    >> int main() {
    >> cout << boolalpha
    >> << "The true expression 0.25 == 0.25000000000000001 yields : "
    >> << (0.25 == 0.25000000000000001) << endl
    >> << "The false expression 0.25 == 0.2500000000000001 yields: "
    >> << (0.25 == 0.2500000000000001) << endl;
    >> }
    >>
    >>
    >> Is it operator overloadin ? Is it good code ?
    >>
    >> TIA
    >>
    >> Adam

    >
    >
    > So what was the output from the code?


    a@acer:~/cpp/comparison$ g++ c.cpp
    a@acer:~/cpp/comparison$ ./a.out
    The true expression 0.25 == 0.25000000000000001 yields : true
    The false expression 0.25 == 0.2500000000000001 yields: false





    Adam
     
    Adam Majewski, Jan 30, 2012
    #11
  12. Scott Lurndal <> wrote:

    (someone asked about)

    >>> if (b == 0.0 && (a == 0.25 || a == -0.75))


    >>Comparing floating point numbers for equality is almost always a bug.


    > Assuming a binary floating point representation, then yes.


    > For decimal representations (BCD fixed and floating point) as
    > implemented by some mainframes and the new decimal support in C,
    > there should be no problems with equality.


    But 0.25 and -0.75 are nice binary fractions. (0.01 and -0.11)

    Even so, I would not suggest actually doing it, but I would
    consider it a bug for a compiler to get wrong.

    Now, ask about decimal fractions that aren't terminating
    binary fractions, and that is a different question.

    -- glen
     
    glen herrmannsfeldt, Feb 13, 2012
    #12
  13. Christian Gollwitzer <> wrote:

    (snip)
    > In this special case it /might/ work, because all values are prefectly
    > representably in binary, i.e. 0.25d=0.01b and 0.75d=0.11b. If a is
    > computed like:


    > double a = 3;
    > a /= 4;


    > then a==0.75 is true on most current systems. However, in most other
    > cases it is not recommended to compare floating point values for equality.


    I believe that C (and C++) require integers to have a binary
    representation, but not floating point values. That a base 13
    floating point would be standard conforming, and fail in cases
    like this.

    (Fortran allows for any integer base greater than one for both
    floating point and integer representations.)

    But on a binary, or other power of two base, system it should work.

    -- glen
     
    glen herrmannsfeldt, Feb 13, 2012
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Motaz Saad
    Replies:
    7
    Views:
    6,491
  2. Philipp
    Replies:
    11
    Views:
    658
    Philipp
    Jan 2, 2007
  3. nw
    Replies:
    14
    Views:
    545
    Victor Bazarov
    May 2, 2007
  4. Saraswati lakki
    Replies:
    0
    Views:
    1,337
    Saraswati lakki
    Jan 6, 2012
  5. Thens

    comparing floating point numbers

    Thens, Jul 10, 2003, in forum: Perl Misc
    Replies:
    3
    Views:
    120
    Michael P. Broida
    Jul 10, 2003
Loading...

Share This Page