Topic: Test equality of double parameter and "magic number" unsafe?


Author: "Daniel M. Pfeffer" <pfefferd@nospam.internet-zahav.net>
Date: 2000/07/19
Raw View
"Niels Dekker" <ndekker@REMOVETHISnki.nl> wrote in message
news:3965D174.6E9C09B4@REMOVETHISnki.nl...
> Given the following MAGIC_NUMBER macro and IsMagic function:
>
>   #define MAGIC_NUMBER 1.23456789E30
>
>   bool IsMagic(const double d)
>   {
>     return d == MAGIC_NUMBER;
>   }
>
> Does C++ guarantee that the following function call returns true?
>   IsMagic(MAGIC_NUMBER);
> I hope so!
>
> In general it may be unsafe to use == to compare floating point numbers,
> but in this case I can't see anything wrong!
>
> Even if my "magic number" can't be represented exactly as a double
> I don't see a problem. I assume that exactly the same roundoff error
> will be made when MAGIC_NUMBER is passed as an argument of IsMagic as
> when it passed as the right hand side of the operator ==.
>
> All of the compilers I checked (BC++ 5.5, MSVC++ 6 SP3, egcs-1.1b g++)
> produce code that returns true when calling IsMagic(MAGIC_NUMBER).
> But I have to be sure that this is the case for any decent C++ compiler!
>
> If it is not guaranteed by the Standard, will it be if I use a constant
> instead of a macro?
> This:
>    const double MAGIC_NUMBER = 1.23456789E30;
> instead of this:
>   #define MAGIC_NUMBER 1.23456789E30

As far as I can see, whether MAGIC_NUMBER is a constant or a macro is
irrelevant in this case. Both define a constant expression of type 'double',
which is compared to a 'double'. If the types were different - the answer
would depend on whether MAGIC_NUMBER is exactly representable in the format
of 'x'. For example:

const long double MAGIC_NUMBER = std::atan(1.0l);        // Pi

bool IsMagic(double x)
{
    return (x == MAGIC_NUMBER);
}

will always fail if 'double' is less precise than 'long double', because
when x is converted to 'long double' - the extra mantissa bits are zeroed.

Problems of this sort can also occur in certain machines that evaluate
intermediate expressions to higher precision than the entire expression
requires (e.g. Intel processors), giving a "double rounding" effect - the
infinitely-precise result is rounded once to the extended precision then
again to the final precision. In such cases the computed value may be one
bit off, causing much head-scratching. The only way to deal with such
problems is to set the FPU to not use extended precision for intermediate
calculations. Your compiler probably has a (non-portable) method of doing
so.


Daniel Pfeffer


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Ken Hagan" <K.Hagan@thermoteknix.co.uk>
Date: 2000/07/12
Raw View
> Niels Dekker wrote:
>
> Given the following MAGIC_NUMBER macro and IsMagic function:
>
>   #define MAGIC_NUMBER 1.23456789E30
>
>   bool IsMagic(const double d)
>   {
>     return d == MAGIC_NUMBER;
>   }
>
> Does C++ guarantee that the following function call returns true?
>   IsMagic(MAGIC_NUMBER);
> I hope so!

I think it does. MAGIC_NUMBER is a floating point literal of
"double" type, so it is exactly representable as a double by
virtue of its very construction.

(At this point, I have nagging doubts as to whether the compiler
is required to evaluate floating point constants according to the
target environment's properties. My doubt is that the target FP
environment isn't required to be fixed.)

"James Kuyper" <kuyper@wizard.net> wrote in message
news:3966777C.ED0A67C5@wizard.net...
> Dangerous assumption. Real implementations will sometimes use
> different-sized floating point registers for different steps in a
> calculation, depending upon what's being done. For instance, on some
> implementations 8 byte floating point numbers are sometimes passed
> around using 10 byte floating point registers. The result is that
> rounding can go in different directions.

Even if they do, isn't the longer representation merely zero-extended,
and therefore "exact" and therefore won't change when rounded back?

...and isn't the program required to perform the "==" at double
precision? (If this isn't the case, then presumably we could still
make it work by storing MAGIC_NUMBER as a static constant.)


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 2000/07/09
Raw View
Given the following MAGIC_NUMBER macro and IsMagic function:

  #define MAGIC_NUMBER 1.23456789E30

  bool IsMagic(const double d)
  {
    return d == MAGIC_NUMBER;
  }

Does C++ guarantee that the following function call returns true?
  IsMagic(MAGIC_NUMBER);
I hope so!

In general it may be unsafe to use == to compare floating point numbers,
but in this case I can't see anything wrong!

Even if my "magic number" can't be represented exactly as a double
I don't see a problem. I assume that exactly the same roundoff error
will be made when MAGIC_NUMBER is passed as an argument of IsMagic as
when it passed as the right hand side of the operator ==.

All of the compilers I checked (BC++ 5.5, MSVC++ 6 SP3, egcs-1.1b g++)
produce code that returns true when calling IsMagic(MAGIC_NUMBER).
But I have to be sure that this is the case for any decent C++ compiler!

If it is not guaranteed by the Standard, will it be if I use a constant
instead of a macro?
This:
   const double MAGIC_NUMBER = 1.23456789E30;
instead of this:
  #define MAGIC_NUMBER 1.23456789E30


Thanks in advance,

Niels Dekker
ndekker "at" nki "dot" nl

P.S. I already posed this question on comp.lang.c++ and
alt.comp.lang.learn.c-c++
but haven't got _the_ answer yet!

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/07/09
Raw View
Niels Dekker wrote:
>
> Given the following MAGIC_NUMBER macro and IsMagic function:
>
>   #define MAGIC_NUMBER 1.23456789E30
>
>   bool IsMagic(const double d)
>   {
>     return d == MAGIC_NUMBER;
>   }
>
> Does C++ guarantee that the following function call returns true?
>   IsMagic(MAGIC_NUMBER);
> I hope so!
>
> In general it may be unsafe to use == to compare floating point numbers,
> but in this case I can't see anything wrong!
>
> Even if my "magic number" can't be represented exactly as a double
> I don't see a problem. I assume that exactly the same roundoff error
> will be made when MAGIC_NUMBER is passed as an argument of IsMagic as
> when it passed as the right hand side of the operator ==.

Dangerous assumption. Real implementations will sometimes use
different-sized floating point registers for different steps in a
calculation, depending upon what's being done. For instance, on some
implementations 8 byte floating point numbers are sometimes passed
around using 10 byte floating point registers. The result is that
rounding can go in different directions.

As a practical matter, you can safely compare for equality integers
smaller than the smallest integer that can't be represented exactly, but
the C++ standard doesn't even say that.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 2000/07/08
Raw View
Given the following MAGIC_NUMBER macro and IsMagic function:

  #define MAGIC_NUMBER 1.23456789E30

  bool IsMagic(const double d)
  {
    return d == MAGIC_NUMBER;
  }

Does C++ guarantee that the following function call returns true?
  IsMagic(MAGIC_NUMBER);
I hope so!

In general it may be unsafe to use == to compare floating point numbers,
but in this case I can't see anything wrong!

Even if my "magic number" can't be represented exactly as a double
I don't see a problem. I assume that exactly the same roundoff error
will be made when MAGIC_NUMBER is passed as an argument of IsMagic as
when it passed as the right hand side of the operator ==.

All of the compilers I checked (BC++ 5.5, MSVC++ 6 SP3, egcs-1.1b g++)
produce code that returns true when calling IsMagic(MAGIC_NUMBER).
But I have to be sure that this is the case for any decent C++ compiler!

If it is not guaranteed by the Standard, will it be if I use a constant
instead of a macro?
This:
   const double MAGIC_NUMBER = 1.23456789E30;
instead of this:
  #define MAGIC_NUMBER 1.23456789E30


Thanks in advance,

Niels Dekker
ndekker "at" nki "dot" nl

P.S. I already posed this question on comp.lang.c++ and
alt.comp.lang.learn.c-c++
but haven't got _the_ answer yet!

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]