public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* RE: Strange behavior
@ 2002-03-03 21:26 Robert Collins
  0 siblings, 0 replies; 8+ messages in thread
From: Robert Collins @ 2002-03-03 21:26 UTC (permalink / raw)
  To: Chuck Allison, Richard R. Malloy, Randall R Schulz; +Cc: Ross Smith, cygwin

Floating point comparisons should _always_ be done via a confidence
interval, not bitwise equality. As for determinism, I don't know what
the logic circuits look like, so can't and won't comment :}.

Rob



> -----Original Message-----
> From: Chuck Allison [mailto:cda@freshsources.com] 
> Sent: Monday, March 04, 2002 4:08 PM
> To: Richard R. Malloy; Randall R Schulz
> Cc: Ross Smith; cygwin@cygwin.com
> Subject: Re: Strange behavior
> 
> 
> That's the point. They're always redued, so in both cases, 
> the expression 2.0/3.0 is evaluated. How can that be 
> non-deterministic?
> 
> ----- Original Message -----
> From: "Richard R. Malloy" <rrmalloy@attbi.com>
> To: "Randall R Schulz" <rrschulz@cris.com>
> Cc: "Ross Smith" <rosss@pharos.co.nz>; "'Chuck Allison'" 
> <cda@freshsources.com>; <cygwin@cygwin.com>
> Sent: Sunday, March 03, 2002 9:47 PM
> Subject: Re: Strange behavior
> 
> 
> > OK. I'm no IA32 expert can someone explain the following 
> results.  (Do 
> > the floating point registers use guard bits, randomly initialized 
> > perhaps?)
> >
> > bool operator==(const Rational& r1, const Rational& r2)
> > {
> >   double a=r1.toDouble(), b=r2.toDouble();
> >   cout << ?== a " << a << " " << ?== b " << b << endl;
> >   return a == b;
> >   //  return r1.toDouble() == r2.toDouble();
> >   /*  return ( r1.numerator == r2.numerator && r1.denominator == 
> > r2.denominator ); */ }

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

^ permalink raw reply	[flat|nested] 8+ messages in thread
* RE: Strange behavior
@ 2002-03-03 21:42 Gareth Pearce
  0 siblings, 0 replies; 8+ messages in thread
From: Gareth Pearce @ 2002-03-03 21:42 UTC (permalink / raw)
  To: cygwin


>Floating point comparisons should _always_ be done via a confidence
>interval, not bitwise equality. As for determinism, I don't know what
>the logic circuits look like, so can't and won't comment :}.
>
>Rob

confidence intervals are indeed the only way...

but as to determinism ... its a function of your compiler I believe.  
Differences will likely arrise with or without optimisation.
Which coincidently - is also the difference between the 2 situations below, 
1 is an optimisation of the other, the assembly produced, even without an 
optimisation flag, will be different, which means different results (one 
case needs temporary variables - other one does not).  So it should be 
deterministic for a single set of assembly, for a given system type... 
although someone could easily of made a processor in which I am wrong.

Gareth
>
>
>
> > -----Original Message-----
> > From: Chuck Allison [mailto:cda@freshsources.com]
> > Sent: Monday, March 04, 2002 4:08 PM
> > To: Richard R. Malloy; Randall R Schulz
> > Cc: Ross Smith; cygwin@cygwin.com
> > Subject: Re: Strange behavior
> >
> >
> > That's the point. They're always redued, so in both cases,
> > the expression 2.0/3.0 is evaluated. How can that be
> > non-deterministic?
> >
> > ----- Original Message -----
> > From: "Richard R. Malloy" <rrmalloy@attbi.com>
> > To: "Randall R Schulz" <rrschulz@cris.com>
> > Cc: "Ross Smith" <rosss@pharos.co.nz>; "'Chuck Allison'"
> > <cda@freshsources.com>; <cygwin@cygwin.com>
> > Sent: Sunday, March 03, 2002 9:47 PM
> > Subject: Re: Strange behavior
> >
> >
> > > OK. I'm no IA32 expert can someone explain the following
> > results.  (Do
> > > the floating point registers use guard bits, randomly initialized
> > > perhaps?)
> > >
> > > bool operator==(const Rational& r1, const Rational& r2)
> > > {
> > >   double a=r1.toDouble(), b=r2.toDouble();
> > >   cout << ?== a " << a << " " << ?== b " << b << endl;
> > >   return a == b;
> > >   //  return r1.toDouble() == r2.toDouble();
> > >   /*  return ( r1.numerator == r2.numerator && r1.denominator ==
> > > r2.denominator ); */ }
>
>--
>Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
>Bug reporting:         http://cygwin.com/bugs.html
>Documentation:         http://cygwin.com/docs.html
>FAQ:                   http://cygwin.com/faq/
>




_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp.


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

^ permalink raw reply	[flat|nested] 8+ messages in thread
* RE: Strange behavior
@ 2002-03-03 18:05 Ross Smith
  2002-03-03 18:32 ` Randall R Schulz
  0 siblings, 1 reply; 8+ messages in thread
From: Ross Smith @ 2002-03-03 18:05 UTC (permalink / raw)
  To: 'Chuck Allison', cygwin

> From: Chuck Allison [mailto:cda@freshsources.com]
> 
> I have a simple Rational number class and have discovered  
> weird behavior
> with Cygwin's g++. If you look at the very short main program in file
> rtest2.cpp, you will see by the output that g++ get's the 
> wrong answer for
> 
> r1 / r2 == Rational(2,3); // should be true
> 
> even though it prints as 2/3! Borland and Microsoft get it 
> right. Any ideas?
> All code atached.

[relevant bit of code]

inline bool operator==(const Rational& r1, const Rational& r2)
{
   return r1.toDouble() == r2.toDouble();
}

This is nothing to do with Cygwin, or g++ for that matter. You're
comparing floating point numbers. Of course it's not reliable! If
other compilers happened to give you an exact equality on that
particular combination of arguments, it was pure luck.

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

^ permalink raw reply	[flat|nested] 8+ messages in thread
* Strange behavior
@ 2002-03-02 13:18 Chuck Allison
  2002-03-02 15:09 ` David Means
  0 siblings, 1 reply; 8+ messages in thread
From: Chuck Allison @ 2002-03-02 13:18 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 477 bytes --]

I have a simple Rational number class and have discovered  weird behavior
with Cygwin's g++. If you look at the very short main program in file
rtest2.cpp, you will see by the output that g++ get's the wrong answer for

r1 / r2 == Rational(2,3); // should be true

even though it prints as 2/3! Borland and Microsoft get it right. Any ideas?
All code atached.

Thanks.

-- Chuck Allison (The Harmonious CodeSmith)
-- Senior Editor, C/C++ Users Journal
-- cda@freshsources.com


[-- Attachment #2: Rational2.h --]
[-- Type: text/plain, Size: 2721 bytes --]

#ifndef RATIONAL_H
#define RATIONAL_H

#include <cassert>
#include <iosfwd>

using std::istream;
using std::ostream;

class Rational
{
   int numerator;
   int denominator;
   void reduce();
   double toDouble() const;

public:
   Rational(int numerator = 0, int denominator = 1);
   Rational operator-() const;
   friend Rational operator+(const Rational&, const Rational&);
   friend Rational operator-(const Rational&, const Rational&);
   friend Rational operator*(const Rational&, const Rational&);
   friend Rational operator/(const Rational&, const Rational&);
   friend ostream& operator<<(ostream&, const Rational&);

   // Extra credit stuff
   Rational& operator+=(const Rational&);
   Rational& operator-=(const Rational&);
   Rational& operator*=(const Rational&);
   Rational& operator/=(const Rational&);
   friend istream& operator>>(istream&, Rational&);
   friend bool operator<(const Rational&, const Rational&);
   friend bool operator>(const Rational&, const Rational&);
   friend bool operator<=(const Rational&, const Rational&);
   friend bool operator>=(const Rational&, const Rational&);
   friend bool operator==(const Rational&, const Rational&);
   friend bool operator!=(const Rational&, const Rational&);
};

inline Rational::Rational(int numerator, int denominator)
{
   this->numerator = numerator;
   this->denominator = denominator;
   assert(denominator != 0);
   reduce();
}

inline Rational Rational::operator-() const
{
   return Rational(-numerator, denominator);
}

inline Rational operator+(const Rational& r1, const Rational& r2)
{
   Rational temp(r1);
   return temp += r2;
}

inline Rational operator-(const Rational& r1, const Rational& r2)
{
   Rational temp(r1);
   return temp -= r2;
}

inline Rational operator*(const Rational& r1, const Rational& r2)
{
   Rational temp(r1);
   return temp *= r2;
}

inline Rational operator/(const Rational& r1, const Rational& r2)
{
   Rational temp(r1);
   return temp /= r2;
}

inline bool operator<(const Rational& r1, const Rational& r2)
{
   return r1.toDouble() < r2.toDouble();
}

inline bool operator>(const Rational& r1, const Rational& r2)
{
   return r1.toDouble() > r2.toDouble();
}

inline bool operator<=(const Rational& r1, const Rational& r2)
{
   return r1.toDouble() <= r2.toDouble();
}

inline bool operator>=(const Rational& r1, const Rational& r2)
{
   return r1.toDouble() >= r2.toDouble();
}

inline bool operator==(const Rational& r1, const Rational& r2)
{
   return r1.toDouble() == r2.toDouble();
}

inline bool operator!=(const Rational& r1, const Rational& r2)
{
   return !(r1.toDouble() == r2.toDouble());
}

inline double Rational::toDouble() const
{
   return double(numerator)/denominator;
}

#endif


[-- Attachment #3: Rational2.cpp --]
[-- Type: text/plain, Size: 1464 bytes --]

#include "Rational2.h"
#include <iostream>
#include <cstdlib>
using namespace std;

// gcd functions: would normally be a static members
int gcd2(int x, int y)
{
   return (y == 0) ? x : gcd2(y, x%y);
}

int gcd(int x, int y)
{
   // Force result to be positive
   return gcd2(abs(x), abs(y));
}

void Rational::reduce()
{
   int div = gcd(numerator, denominator);
   assert(div > 0);
   if (div != 1)
   {
      numerator /= div;
      denominator /= div;
   }
}

Rational& Rational::operator+=(const Rational& r)
{
   numerator = numerator*r.denominator + denominator*r.numerator;
   denominator = denominator*r.denominator;
   reduce();
   return *this;
}

Rational& Rational::operator-=(const Rational& r)
{
   numerator = numerator*r.denominator - denominator*r.numerator;
   denominator = denominator*r.denominator;
   reduce();
   return *this;
}

Rational& Rational::operator*=(const Rational& r)
{
   numerator *= r.numerator;
   denominator *= r.denominator;
   reduce();
   return *this;
}

Rational& Rational::operator/=(const Rational& r)
{
   assert(r.numerator != 0);
   numerator *= r.denominator;
   denominator *= r.numerator;
   reduce();
   return *this;
}

istream& operator>>(istream& is, Rational& r)
{
   char slash;
   is >> r.numerator >> slash;
   assert(slash == '/');
   is >> r.denominator;
   r.reduce();
   return is;
}

ostream& operator<<(ostream& os, const Rational& r)
{
   return os << r.numerator << '/' << r.denominator;
}



[-- Attachment #4: rtest2.cpp --]
[-- Type: text/plain, Size: 508 bytes --]

#include <iostream>
#include "Rational2.h"
using namespace std;

int main()
{
   Rational r1(1,2), r2(3,4);
   cout << r1 + r2 << endl;
   cout << (r1 + r2 == Rational(5,4)) << endl;
   cout << r1 - r2 << endl;
   cout << (r1 - r2 == Rational(-1,4)) << endl;
   cout << r1 * r2 << endl;
   cout << (r1 * r2 == Rational(3,8)) << endl;
   cout << r1 / r2 << endl;
   cout << (r1 / r2 == Rational(2,3)) << endl;
}

/* Cygwin output:
5/4
1
-1/4
1
3/8
1
2/3
0
*/

/* Other compilers
5/4
1
-1/4
1
3/8
1
2/3
1
*/



[-- Attachment #5: Type: text/plain, Size: 214 bytes --]

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2002-03-04  5:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-03 21:26 Strange behavior Robert Collins
  -- strict thread matches above, loose matches on Subject: below --
2002-03-03 21:42 Gareth Pearce
2002-03-03 18:05 Ross Smith
2002-03-03 18:32 ` Randall R Schulz
2002-03-03 20:49   ` Richard R. Malloy
2002-03-03 21:08     ` Chuck Allison
2002-03-02 13:18 Chuck Allison
2002-03-02 15:09 ` David Means

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).