## digitalmars.D.learn - type comparisons

Denton Cockburn <diboss hotmail.com> writes:
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

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
Denton Cockburn <diboss hotmail.com> writes:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[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
Bill Baxter <dnewsgroup billbaxter.com> writes:
Denton Cockburn wrote:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[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
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
=?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= <jeberger free.fr> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Denton Cockburn wrote:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[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;
Here, you're computing "a + 0.1" using double, then converting it to real
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); // 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
Denton Cockburn <diboss hotmail.com> writes:
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 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;
Here, you're computing "a + 0.1" using double, then converting it to real
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); // 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
Bill Baxter <dnewsgroup billbaxter.com> writes:
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 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;
Here, you're computing "a + 0.1" using double, then converting it to real
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); // 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.
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
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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.
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" <schveiguy yahoo.com> writes:
"Steven Schveighoffer" wrote
To work correctly, you should always compare floating point values by