[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: g++ bug with double function result in <= expression? (corrected)
From: |
Guy Harrison |
Subject: |
Re: g++ bug with double function result in <= expression? (corrected) |
Date: |
Wed, 06 Oct 2004 22:00:00 GMT |
User-agent: |
KNode/0.7.7 |
Jonathan Knispel wrote:
> [Sorry for the repost, I accidentally included bogus code in the original]
>
> This looks a bit like a compiler bug to me, but I may be missing
> something
> obvious. :-)
Floating point equality tests = avoid like plague! :-)
> The code's below. "a" and "b" are a pair of structs with identical
> values, but "a.toReal() <= b.toReal()" returns true if toReal() is defined
> with a float return value (expected) and false if defined with a double
> return value (huh?). If I assign the results of the calls to a pair of
> appropriately typed variables and test the variables with <=, the problem
> goes away (workaround).
>
> Here's the sample output from a couple of runs:
>
> Using double
> a < b false
> a <= b false
> ad < bd false
> ad <= bd true
>
> Using float
> a < b false
> a <= b true
> ad < bd false
> ad <= bd true
>
> I've tried with g++ 3.2.2 (i386-redhat-linux), 3.3.3 (i586-suse-linux)
> and
> 3.4.2 (i686-pc-linux-gnu). Stepping through in gdb, the values all look
> fine, but the <= test goes through to the false logic, even though
> evealuating "a.toReal() <= b.toReal()" in gdb returns true. Any ideas?
>
> Thanks in advance,
> Jonathan
>
> #include <sys/time.h>
> #include <iostream>
>
> using std::cout;
>
> #if 1
>
> typedef double RealType;
> const char* realTypeName = "double";
>
> #else
>
> typedef float RealType;
> const char* realTypeName = "float";
>
> #endif
>
> struct TimeVal : public timeval
> {
> TimeVal(RealType t) {
> tv_sec = static_cast<unsigned int>(t);
> tv_usec = static_cast<unsigned int>(1e6 * (t - tv_sec));
> }
>
> RealType toReal() { return tv_sec + 1e-6 * tv_usec; }
^^^
Fault. You can hide the problem by changing 1e-6 to 1000000 but the
fundamental issue is the class uses floating point. You need a precise
representation (if floats "worked" then timeval would use one). Rough hints
on possible ctors...
TimeVal (std::time_t s, long u);
TimeVal (const std::pair<std::time_t,long> &);
TimeVal (const std::string &);
> };
>
> int
> main(int argc,
> char** argv)
> {
> cout << "Using " << realTypeName << '\n';
>
> TimeVal a(2.1);
> TimeVal b(2.1);
>
> if (a.toReal() < b.toReal())
^^^
You can hide this...
bool operator<(const TimeVal &)const;
...now you can write...
if (a < b)
> cout << "a < b true\n";
> else
> cout << "a < b false\n";
>
> if (a.toReal() <= b.toReal())
^^^
Ditto - operator<=(const TimeVal &)const;
> cout << "a <= b true\n";
> else
> cout << "a <= b false\n";
>
> RealType ad = a.toReal();
> RealType bd = b.toReal();
>
> if (ad < bd)
> cout << "ad < bd true\n";
> else
> cout << "ad < bd false\n";
>
> if (ad <= bd)
> cout << "ad <= bd true\n";
> else
> cout << "ad <= bd false\n";
> }