digitalmars.D.learn - type comparisons
- Denton Cockburn (10/10) Jan 26 2008 Why does this throw these assert errors?
- BCS (4/15) Jan 26 2008 rounding error?
- Denton Cockburn (12/20) Jan 26 2008 I can't think of a reason that would be acceptable.
- Bill Baxter (6/29) Jan 26 2008 You should never compare floating point values using ==. It's not D's
- =?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= (20/43) Jan 26 2008 -----BEGIN PGP SIGNED MESSAGE-----
- Denton Cockburn (2/51) Jan 26 2008 The problem I'm having is that we are comparing the same numerical value...
- Bill Baxter (9/60) Jan 26 2008 One tenth is not exactly representable in floating point. Therefore you...
- Steven Schveighoffer (18/20) Jan 28 2008 This is inherent in floating point. This happens in other languages as
- Steven Schveighoffer (4/10) Jan 28 2008 Er... this should be:
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,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[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.
Jan 26 2008
Denton Cockburn wrote:On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote: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); --bbReply to Denton,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[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.
Jan 26 2008
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Denton Cockburn wrote:On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Here, you're computing "a + 0.1" using double, then converting it to realReply to Denton,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;[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.b -= 0.1; assert(b == a); // fails real c = a; c += 0.1;Here, you converted a to real, then you add 0.1 using real.c -= 0.1; assert(c == a); // passesWhich 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:The problem I'm having is that we are comparing the same numerical value for equality, and getting a (logically) false result.On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Here, you're computing "a + 0.1" using double, then converting it to realReply to Denton,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;[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.b -= 0.1; assert(b == a); // fails real c = a; c += 0.1;Here, you converted a to real, then you add 0.1 using real.c -= 0.1; assert(c == a); // passesWhich 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
Denton Cockburn wrote:Jérôme M. Berger Wrote: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-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Denton Cockburn wrote:The problem I'm having is that we are comparing the same numerical value for equality, and getting a (logically) false result.On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:Here, you're computing "a + 0.1" using double, then converting it to realReply to Denton,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;[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.b -= 0.1; assert(b == a); // fails real c = a; c += 0.1;Here, you converted a to real, then you add 0.1 using real.c -= 0.1; assert(c == a); // passesWhich 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
"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