comparing floating point numbers

A

Adam Majewski

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
 
B

BCFD36

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

MikeWhy

BCFD36 said:
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.
 
A

Alf P. Steinbach

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
 
M

Marcel Müller

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
 
B

BCFD36

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

LR

Adam said:
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
 
M

Miles Bader

BCFD36 said:
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
 
N

Nick Keighley

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
 
J

Juha Nieminen

Miles Bader said:
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
 
A

Adam Majewski

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
 
G

glen herrmannsfeldt

(someone asked about)
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
 
G

glen herrmannsfeldt

(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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top