## digitalmars.D.learn - type comparisons

- Denton Cockburn <diboss hotmail.com> Jan 26 2008
- BCS <ao pathlink.com> Jan 26 2008
- Denton Cockburn <diboss hotmail.com> Jan 26 2008
- Bill Baxter <dnewsgroup billbaxter.com> Jan 26 2008
- =?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= <jeberger free.fr> Jan 26 2008
- Denton Cockburn <diboss hotmail.com> Jan 26 2008
- Bill Baxter <dnewsgroup billbaxter.com> Jan 26 2008
- "Steven Schveighoffer" <schveiguy yahoo.com> Jan 28 2008
- "Steven Schveighoffer" <schveiguy yahoo.com> Jan 28 2008

Why does this throw these assert errors? both are thrown. All 3 - DMD 2.008/2.009/2.010 void main() { real x = 0.6584L; double y = 0.6584; assert(x == y); assert(cast(double)x == y); }

Jan 26 2008

Reply to Denton,Why does this throw these assert errors? both are thrown. All 3 - DMD 2.008/2.009/2.010 void main() { real x = 0.6584L; double y = 0.6584; assert(x == y); assert(cast(double)x == y); }

rounding error? rounding 0.6584 (base 10) to real and then converting to double may round different than rounding it directly to double.

Jan 26 2008

On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Reply to Denton,[quoted text muted]

rounding error? rounding 0.6584 (base 10) to real and then converting to double may round different than rounding it directly to double.

I can't think of a reason that would be acceptable. This means I can't reliably do operations with converted reals/doubles :( This is also weird: double a = 0.65; real b = a + 0.1; b -= 0.1; assert(b == a); // fails real c = a; c += 0.1; c -= 0.1; assert(c == a); // passes

Jan 26 2008

Denton Cockburn wrote:On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Reply to Denton,[quoted text muted]

rounding 0.6584 (base 10) to real and then converting to double may round different than rounding it directly to double.

I can't think of a reason that would be acceptable. This means I can't reliably do operations with converted reals/doubles :( This is also weird: double a = 0.65; real b = a + 0.1; b -= 0.1; assert(b == a); // fails real c = a; c += 0.1; c -= 0.1; assert(c == a); // passes

You should never compare floating point values using ==. It's not D's fault, it's the lossy nature of floating point calculations themselves. Instead do something like assert(abs(c-a) < rounding_tolerance); --bb

Jan 26 2008

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Denton Cockburn wrote:On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Reply to Denton,[quoted text muted]

rounding 0.6584 (base 10) to real and then converting to double may round different than rounding it directly to double.

I can't think of a reason that would be acceptable. This means I can't reliably do operations with converted reals/doubles :( This is also weird: double a = 0.65; real b = a + 0.1;

to realb -= 0.1; assert(b == a); // fails real c = a; c += 0.1;

c -= 0.1; assert(c == a); // passes

Which could explain that rounding errors wind up different and make one assertion pass while the other fails. Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHm4y1d0kWM4JG3k8RAgfQAKC3LwsQfklEVT+cP2w3HrR/xtK6JACfdPr9 PQIwRTbf2zyhpst9zdeZn9s= =RA4Q -----END PGP SIGNATURE-----

Jan 26 2008

Jérôme M. Berger Wrote:-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Denton Cockburn wrote:On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Reply to Denton,[quoted text muted]

rounding 0.6584 (base 10) to real and then converting to double may round different than rounding it directly to double.

I can't think of a reason that would be acceptable. This means I can't reliably do operations with converted reals/doubles :( This is also weird: double a = 0.65; real b = a + 0.1;

to realb -= 0.1; assert(b == a); // fails real c = a; c += 0.1;

c -= 0.1; assert(c == a); // passes

Which could explain that rounding errors wind up different and make one assertion pass while the other fails. Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHm4y1d0kWM4JG3k8RAgfQAKC3LwsQfklEVT+cP2w3HrR/xtK6JACfdPr9 PQIwRTbf2zyhpst9zdeZn9s= =RA4Q -----END PGP SIGNATURE-----

The problem I'm having is that we are comparing the same numerical value for equality, and getting a (logically) false result.

Jan 26 2008

Denton Cockburn wrote:Jérôme M. Berger Wrote:-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Denton Cockburn wrote:On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:[quoted text muted]

rounding 0.6584 (base 10) to real and then converting to double may round different than rounding it directly to double.

This means I can't reliably do operations with converted reals/doubles :( This is also weird: double a = 0.65; real b = a + 0.1;

to realb -= 0.1; assert(b == a); // fails real c = a; c += 0.1;

c -= 0.1; assert(c == a); // passes

one assertion pass while the other fails. Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHm4y1d0kWM4JG3k8RAgfQAKC3LwsQfklEVT+cP2w3HrR/xtK6JACfdPr9 PQIwRTbf2zyhpst9zdeZn9s= =RA4Q -----END PGP SIGNATURE-----

The problem I'm having is that we are comparing the same numerical value for equality, and getting a (logically) false result.

One tenth is not exactly representable in floating point. Therefore you get rounding errors the moment you try to store .1 in a float/double/real. real can represent 1/10 a bit more accurately than double. So .1 as a double, then cast to a real is not quite the same as .1 that started as a real. Try .125 or 0.0625 and you'll get a good answer. But .1 is bad news for floating point. --bb

Jan 26 2008

"Denton Cockburn" wroteThe problem I'm having is that we are comparing the same numerical value for equality, and getting a (logically) false result.

This is inherent in floating point. This happens in other languages as well. The problem is that .1 is like 1/3 in decimal. Decimal cannot accurately represent 1/3 because it is a repeating decimal (0.3333...). Likewise, floating point, which is base-2, cannot represent all decimal values accurately. For an in-depth explanation, see http://en.wikipedia.org/wiki/Floating_point Skip to the section on Accuracy. To work correctly, you should always compare floating point values by adding some small error. So instead of: assert(x > y) you write const myError = 1e-10; assert(x + myError > y) Equality looks something more like: assert(fabs(x - y) < myError) -Steve

Jan 28 2008

"Steven Schveighoffer" wroteTo work correctly, you should always compare floating point values by adding some small error. So instead of: assert(x > y) you write const myError = 1e-10; assert(x + myError > y)

Er... this should be: assert(x - myError > y) -Steve

Jan 28 2008